Compare commits

..

356 Commits

Author SHA1 Message Date
Kim Morrison
26e0fe2559 wip 2025-07-24 17:10:31 +10:00
Kim Morrison
04e81de579 initial look at noncomputable getter 2025-07-24 16:42:44 +10:00
Kim Morrison
3cde12567f feat: add HPow Int field to Field (#9500)
This PR adds a `HPow \a Int \a` field to `Lean.Grind.Field`, and
sufficient axioms to connect it to the operations, so that in future we
can reason about exponents in `grind`. To avoid collisions, we also move
the `HPow \a Nat \a` field in `Semiring` from the extends clause to a
field. Finally, we add some failing tests about normalizing exponents.
2025-07-24 06:00:11 +00:00
Kim Morrison
8d5da6491a chore: remove provable fields from Grind.Nat/IntModule (#9499) 2025-07-24 05:23:35 +00:00
Kim Morrison
eea7e50519 chore: script/release_steps.py only merges nightly-testing on rc1 (#9498) 2025-07-24 04:31:11 +00:00
Lean stage0 autoupdater
c4c3497776 chore: update stage0 2025-07-24 01:57:24 +00:00
Kyle Miller
d45cc674ea feat: make cdot expansion take hygiene into account (#9443)
This PR makes cdot function expansion take hygiene information into
account, fixing "parenthesis capturing" errors that can make erroneous
cdots trigger cdot expansion in conjunction with macros. For example,
given
```lean
macro "baz% " t:term : term => `(1 + ($t))
```
it used to be that `baz% ·` would expand to `1 + fun x => x`, but now
the parentheses in `($t)` do not capture the cdot. We also fix an
oversight where cdot function expansion ignored the fact that type
ascriptions and tuples were supposed to delimit expansion, and also now
the quotation prechecker ignores the identifier in `hygieneInfo`. (#9491
added the hygiene information to the parenthesis and cdot syntaxes.)

This fixes a bug discovered by [Google
DeepMind](https://storage.googleapis.com/deepmind-media/DeepMind.com/Blog/imo-2024-solutions/P1/index.html),
which made use of `useλy . x=>y.rec λS p=>?_`. The `use` tactic from
Mathlib wrapped the provided term in a type ascription, and so this was
equivalent to `use fun x => λy x x=>y.rec λS p=>?_`. (Note that cdot
function expansion is not able to take into account *where* the cdots
are located, and it is syntactically valid to insert an identifier into
the binder list like this. If we ever want to address this in the
future, we could have cdots expand into a special term that wraps an
identifier that evaluates to a local, but which would cause errors in
other contexts.)

Design note: we put the `hygieneInfo` on the open parenthesis rather
than at the end, since that way the hygiene information is available
even when there are parsing errors. This is important since we rely on
being able to elaborate partial syntax to get elab info (e.g. in `(a.`
to get completion info). Note that syntax matchers check that the
`hygieneInfo` is actually present, so such partial syntax would not be
matched.
2025-07-24 00:43:32 +00:00
Cameron Zwarich
8a0d036e82 perf: use an FVarIdHashSet for ReduceArity.State.used (#9497) 2025-07-24 00:25:26 +00:00
Lean stage0 autoupdater
9d93b10919 chore: update stage0 2025-07-23 21:41:23 +00:00
Kyle Miller
2412d52536 feat: add hygiene info to paren/tuple/typeAscription syntaxes (#9491)
This PR adds hygiene info to paren/tuple/typeAscription syntaxes, which
will be used to implement hygienic cdot function expansion in #9443.
2025-07-23 20:57:06 +00:00
Kyle Miller
e686d040ea fix: add missing spaces for pretty printing (#9475)
This PR fixes the way some syntaxes are pretty printed due to missing
whitespace advice.

Removes a vestigal `have'` tactic macro introduced in
0032578d5b back when `let` syntax looked
like `let Type := v`.

While we're here, extends the `let`/`have` docstrings to mention `(eq :=
h)` syntax.

Whitespace issues were reported by Damiano Testa [on
Zulip](https://leanprover.zulipchat.com/#narrow/channel/270676-lean4/topic/Some.20pretty.20printing.20quirks/near/529964215).
2025-07-23 19:35:04 +00:00
Leonardo de Moura
2dce18655d fix: incorrect proof term in grind linarith (#9487)
This PR fixes an incorrect proof term constructed by `grind linarith`,
as reported in #9485.

closes #9485
2025-07-23 17:34:44 +00:00
Kyle Miller
6cf22b32aa feat: custom structure constructors can update binder kinds of parameters (#9480)
This PR adds a feature where `structure` constructors can override the
inferred binder kinds of the type's parameters. In the following, the
`(p)` binder on `toLp` causes `p` to be an explicit parameter to
`WithLp.toLp`:
```lean
structure WithLp (p : Nat) (V : Type) where toLp (p) ::
  ofLp : V
```
This reflects the syntax of the feature added in #7742 for overriding
binder kinds of structure projections. Similarly, only those parameters
in the header of the `structure` may be updated; it is an error to try
to update binder kinds of parameters included via `variable`.

Closes #9072.

Fixes a possible bug from stale caches when creating the type of the
constructor.
2025-07-23 16:33:34 +00:00
Rob23oba
d24219697e feat: unexpand Vector.mk #[...] _ to #v[...] (#8391)
This PR adds an unexpander for `Vector.mk` that unexpands `Vector.mk
#[...] _` to `#v[...]`.
```lean
-- previously:
#check #v[1, 2, 3] -- { toArray := #[1, 2, 3], size_toArray := ⋯ } : Vector Nat 3
-- now:
#check #v[1, 2, 3] -- #v[1, 2, 3] : Vector Nat 3
```

---------

Co-authored-by: Kyle Miller <kmill31415@gmail.com>
2025-07-23 16:27:51 +00:00
Lean stage0 autoupdater
d353a25a36 chore: update stage0 2025-07-23 16:53:11 +00:00
Sebastian Ullrich
9dc4dbebe1 perf: do not try to mmap .ir to the same address as .olean (#9488) 2025-07-23 16:12:44 +00:00
Sebastian Ullrich
04be1c6b5c chore: CI: cached Lake as secondary job (#9486) 2025-07-23 13:26:35 +00:00
Sebastian Ullrich
e46a3108d9 perf: do not export specializations (#9465)
Trading an insignificant amount of IR bloat for better recompilation
avoidance
2025-07-23 13:12:15 +00:00
Sebastian Ullrich
4cbfa485fa chore: fix test on macOS (#9483) 2025-07-23 12:10:13 +00:00
Sebastian Ullrich
9328271dd0 perf: do not export LCNF decls of closed terms (#9484)
This was only necessary when `isDeclMeta` and `isDeclPublic` were
intertwined
2025-07-23 09:50:29 +00:00
Lean stage0 autoupdater
f137d43931 chore: update stage0 2025-07-23 09:39:13 +00:00
Sebastian Ullrich
0ba5413266 refactor: remove unused Environment.extraConstNames (#9470)
Obsoleted in #9356
2025-07-23 08:58:32 +00:00
Sebastian Ullrich
fefc033515 chore: disable artifacts cache for building stage2+ (#9482) 2025-07-23 08:44:08 +00:00
Lean stage0 autoupdater
d888039468 chore: update stage0 2025-07-23 08:54:57 +00:00
Sebastian Ullrich
ddc4cf0a97 refactor: private field use in Meta.Context (#9468)
This PR resolves an issue where the `Meta.Context.configKey` field is
private but we still want to use the constructor of the structure for
setting other fields, which would be prevented by the module system
checks:
```lean
structure Context where
  private config    : Config               := {}
  private configKey : UInt64               := config.toKey
...

def ContextInfo.runMetaM (info : ContextInfo) (lctx : LocalContext) (x : MetaM α) : IO α := do
  -- cannot call private constructor of `Meta.Context`!
  (·.1) <$> info.runCoreM (x.run { lctx := lctx } { mctx := info.mctx })
```
Instead, the private field is extracted into an (existing) structure
that applies its default value:
```lean
/-- Configuration with key produced by `Config.toKey`. -/
structure ConfigWithKey where
  private mk ::
  config : Config := {}
  key    : UInt64 := config.toKey
  
structure Context where
  keyedConfig : ConfigWithKey := default
```
Thus `Context`'s constructor remains public without exposing a way to
set `key` directly.
2025-07-23 08:16:44 +00:00
Leonardo de Moura
aa5b392e35 fix: canonicalization of non-standard OfNat.ofNat terms (#9481)
This PR fixes a kernel type mismatch that occurs when using `grind` on
goals containing non-standard `OfNat.ofNat` terms. For example, in issue
#9477, the `0` in the theorem `range_lower` has the form:
```lean
(@OfNat.ofNat
  (Std.PRange.Bound (Std.PRange.RangeShape.lower (Std.PRange.RangeShape.mk Std.PRange.BoundShape.closed Std.PRange.BoundShape.open)) Nat)
  (nat_lit 0)
  (instOfNatNat (nat_lit 0)))
```
instead of the more standard form:
```lean
(@OfNat.ofNat
  Nat
  (nat_lit 0)
  (instOfNatNat (nat_lit 0)))
```

Closes #9477
2025-07-23 04:10:21 +00:00
Lean stage0 autoupdater
6346fdb253 chore: update stage0 2025-07-23 02:31:29 +00:00
Leonardo de Moura
7d2a7dba81 fix: improve evalInt? (#9479)
This PR improves the `evalInt?` function, which is used to evaluate
configuration parameters from the `ToInt` type class. This PR also adds
a new `evalNat?` function for handling the `IsCharP` type class, and
introduces a configuration option:
```
grind (exp := <num>)
```
This option controls the maximum exponent size considered during
expression evaluation. Previously, `evalInt?` used `whnf`, which could
run out of stack space when reducing terms such as `2^1024`.

closes #9427
2025-07-23 01:51:04 +00:00
Aaron Liu
98f05c47d0 fix: add binrel% macros for notation in Init.Core (#9084)
This PR adds `binrel%` macros for `!=` and `≠` notation defined in
`Init.Core`. This allows the elaborator to insert coercions on both
sides of the relation, instead of committing to the type on the left
hand side.

I first discovered this bug while working on Brouwer's fixed point
theorem. See the discussion on Zulip at [#lean4 > Elaboration of
&#96;≠&#96; @
💬](https://leanprover.zulipchat.com/#narrow/channel/270676-lean4/topic/Elaboration.20of.20.60.E2.89.A0.60/near/526236907).
2025-07-23 01:34:55 +00:00
Mac Malone
67bbc947af feat: lake: meta import support (#9478)
This PR adds proper Lake support for `meta import`. Module IR is now
tracked in traces and in the pre-resolved modules Lake passes to `lean
--setup`.
2025-07-23 01:17:20 +00:00
Leonardo de Moura
64219ac91e fix: assertNatCast in grind (#9476)
This PR fixes the bridge between `Nat` and `Int` in `grind cutsat`.

Closes #9467
2025-07-22 21:59:38 +00:00
Leonardo de Moura
dedd9275ec fix: mkCongrSimpCore? (#9472)
This PR fixes another issue at the `congr_simp` theorems that was
affecting Mathlib. Many thanks to Johan Commelin for creating the mwe.

closes #9466
2025-07-22 18:09:24 +00:00
Sebastian Ullrich
4dbe84dc98 chore: ensure Lake and Lean agree when .ir is needed (#9471) 2025-07-22 17:34:41 +00:00
Giles Shaw
0cc4c91800 fix: change the proof of Nat.zero_mod to rfl (#9391)
This PR replaces the proof of the simplification lemma `Nat.zero_mod`
with
`rfl` since it is, by design, a definitional equality. This solves an
issue
whereby the lemma could not be used by the simplifier when in 'dsimp'
mode.

Closes #9389

---------

Co-authored-by: Joachim Breitner <mail@joachim-breitner.de>
2025-07-22 13:21:48 +00:00
Sebastian Graf
548d564c18 feat: Introduce mleave tactic that leaves the SPred proof mode (#9363) (#9454)
This PR introduces tactic `mleave` that leaves the `SPred` proof mode by
eta expanding through its abstractions and applying some mild
simplifications. This is useful to apply automation such as `grind`
afterwards.

Relates to #9363.
2025-07-22 11:50:16 +00:00
Sebastian Graf
2d30e3913c fix: Handle let/have in mintro (#9365) (#9451)
This PR adds support in the `mintro` tactic for introducing `let`/`have`
binders in stateful targets, akin to `intro`. This is useful when
specifications introduce such let bindings.

Closes #9365.
2025-07-22 11:35:46 +00:00
Joachim Breitner
ec13bb963f fix: PProdN.reduceProjs to also look for projection functions (#9464)
This PR makes `PProdN.reduceProjs` also look for projection functions.
Previously, all redexes were created by the functions in `PProdN`, which
used primitive projections. But with `mkAdmProj` the projection
functions creep in via the types of the `admissible_pprod_fst` theorem.
So let's just reduce both of them.

Fixes #9462.
2025-07-22 09:22:50 +00:00
Lean stage0 autoupdater
9006597f59 chore: update stage0 2025-07-22 09:47:42 +00:00
Sebastian Ullrich
e28569f2a1 perf: minimize exported codegen data (#9356)
To be documented
2025-07-22 09:05:49 +00:00
Kenny Lau
751947482f fix: use let rec for Fin.reverseInduction (#9142)
This PR changes `Fin.reverseInduction` from using well-founded recursion
to using `let rec`, which makes it have better definitional equality.
Co-authored by @digama0. See the test below:

```lean
namespace Fin

/-- The new one. -/
@[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 :=
  let rec go (j : Nat) (h) (h2 : i ≤ j) (x : motive ⟨j, h⟩) : motive i :=
    if hi : i.1 = j then (show i = ⟨j, h⟩ 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

/-- Same code but using reverseInduction'. -/
@[elab_as_elim] def lastCases' {n : Nat} {motive : Fin (n + 1) → Sort _} (last : motive (Fin.last n))
    (cast : ∀ i : Fin n, motive (castSucc i)) (i : Fin (n + 1)) : motive i :=
  reverseInduction' last (fun i _ => cast i) i

end Fin

theorem foo : (Fin.lastCases (-4) (fun i ↦ (i : Int) * 2 + 1) (2 : Fin 3) : Int) = -4 := rfl
#eval (Fin.lastCases (-4) (fun i ↦ (i : Int) * 2 + 1) (2 : Fin 3) : Int)
theorem foo' : (Fin.lastCases' (-4) (fun i ↦ (i : Int) * 2 + 1) (2 : Fin 3) : Int) = -4 := rfl
#eval (Fin.lastCases' (-4) (fun i ↦ (i : Int) * 2 + 1) (2 : Fin 3) : Int)

theorem bar : (Fin.reverseInduction (n := 2) (motive := fun _ ↦ Int)
    (-4) (fun i _ ↦ (i : Int) * 2 + 1) (2 : Fin 3) : Int) = -4 := rfl
#eval (Fin.reverseInduction (n := 2) (motive := fun _ ↦ Int)
    (-4) (fun i _ ↦ (i : Int) * 2 + 1) (2 : Fin 3) : Int)
theorem bar' : (Fin.reverseInduction' (n := 2) (motive := fun _ ↦ Int)
    (-4) (fun i _ ↦ (i : Int) * 2 + 1) (2 : Fin 3) : Int) = -4 := rfl
#eval (Fin.reverseInduction' (n := 2) (motive := fun _ ↦ Int)
    (-4) (fun i _ ↦ (i : Int) * 2 + 1) (2 : Fin 3) : Int)
```
[Link to Lean 4
Web](https://live.lean-lang.org/#project=lean-nightly&codez=HYQwtgpgzgDiDGEAEAxAlsAUJg9AWjyQBUALZYCAdyQHsKA6JPHTAAQG0IAbEAIwH0QUftzRgAukgAmEAGZIAThABuEBVAgBJYFICu8AC5o6AciQBvMDSOqkALlQYkACmBIA1EgCMASiSAkwiQAZRoFAyR+AF8XHihwhysbZGd0YHpY8OAfH0wkPJd4IXikQAAiJDR7RzdgABokRLRbNHoofXgA+utG5MK4oLby7JcKh1SXN09fPwSupvsAXlykLghwpXaAcxoXACtKgDkQAz9nEhOSACZKisATIiQdk4APSobbQAvyHbqSQEvyac6k8oLJZ5NDyEgjcr0LxIeb3JAGMhuZxQEg0agVWEfL7fJC8ACeSCgYhgSHYgATCJDg8R+QAdpEhHsCkNwNPUjvASHDKGgEYy8gAfJAABhhAD5cQSaJANiBeUgBTt3ND5mKtnDnPjaFKQCcNZKINKTr1wljxZr9SAcY8cnlVfwIi5dVq/BlsPhCEFwMh4DQZLjdOFdETgBtFCo1BptHpDMZgCZGMw2JweAIhCIuGJJDJ5BkAMJCaBmcxuByHAzRSyzZCjJyuDzePyBEJhCLRZwZF6VlypdJFJBZa35ZxGyplCFjWr/boFIr9eDtNBDZxjmsTet/V7IEaLPJKVTqLQ6fRGUzLXvOWS6NwVO3KpDDhflbAQHRVbAIiChCBgJCyGjbBwpBgPZxHmGhQC4eAACwnBeV5IIAZYTDJU2jHEgABUSBXJMJxXNWbgAMx/ChfiwlBCyKLIXCYAAxCoIBcF2QG5vm4HOFBMGXoCiFLshwCoRhWH1i4uFVEghG8ccmDvp+36/jQZgAd2zFgWYbHQS4sFcUhDjEehmF1r4wmVGM4k6XxJFMJB5EKJRNF0QxgFpMpBYQep56cRU3EQrpAkGThxlOKZSDEW+ZAybiIAKJUjn0Lu4YHlGx5IsWsIXCcG7kZpdqISF+SuRxcHZdpwXmXpgmGc4IkmURpWkVZdiwjZVG0co9GMWkcX7pGR4xuM5FpS4GUNT+nFFblg7sRpHn2l5El+L52FGXhYk1ZJ0lKN+vCRQp7WxWGXWHtGJ61sNA3OENsJZQhJWSXlakFYCRU8WZ/H6YtlUBQRq0WWRw1NXZrUOd2nURodSWqSlmHpZ2w1XTl5mMvdU2Fddz03fNb1CR9y1BcRQA)

Notice how `rfl` fails for the 1st and 5th tests that use the original
`Fin.reverseInduction`, but the 3rd and 7th tests that use the new code
in this PR succeed.

Closes #9141.

---------

Co-authored-by: Markus Himmel <markus@lean-fro.org>
2025-07-22 08:34:14 +00:00
Rob23oba
b7ab7ea745 fix: behavior of String.next (#9449)
This PR fix the behavior of `String.next` on the scalar boundary (`2 ^
63 - 1` on 64-bit platforms).

Closes #9440
2025-07-22 06:48:33 +00:00
Cameron Zwarich
6f5532f069 perf: make function types object rather than tobject (#9461) 2025-07-22 01:16:45 +00:00
Cameron Zwarich
30ca6c82e0 refactor: use named params (#9460) 2025-07-22 00:11:25 +00:00
Cameron Zwarich
968a708a9f perf: update type information in cases arms for RC optimizations (#9457)
The `isRef` check being removed here used to be an optimization, because
this structure only tracked whether ref counting operations need to be
inserted at all. Now the structure also tracks whether the value needs
to be checked for being a scalar or not, which is something that can be
refined by a `cases` arm, since inductive types can have a mix of scalar
and non-scalar constructors.
2025-07-21 23:10:11 +00:00
Cameron Zwarich
bb23700f24 chore: add named params to MonadWithReader.withReader (#9459)
This matches `MonadWithReaderOf`.
2025-07-21 23:02:19 +00:00
Cameron Zwarich
9a34f6bc95 refactor: remove questionable defaults in Context structure (#9458) 2025-07-21 22:16:14 +00:00
Cameron Zwarich
f3e1795175 refactor: clean up monad setup (#9456) 2025-07-21 21:22:20 +00:00
jrr6
d57d1fcd36 fix: prevent deriving handlers from generating ambiguous identifiers (#9371)
This PR fixes an issue that caused some `deriving` handlers to fail when
the name of the type being declared matched that of a declaration in an
open namespace.

Closes #9366
2025-07-21 17:45:54 +00:00
Lean stage0 autoupdater
e134cfea8f chore: update stage0 2025-07-21 16:24:20 +00:00
Marc Huisinga
8b8561a699 feat: improved go to definition (#9040)
This PR improves the 'Go to Definition' UX, specifically:
- Using 'Go to Definition' on a type class projection will now extract
the specific instances that were involved and provide them as locations
to jump to. For example, using 'Go to Definition' on the `toString` of
`toString 0` will yield results for `ToString.toString` and `ToString
Nat`.
- Using 'Go to Definition' on a macro that produces syntax with type
class projections will now also extract the specific instances that were
involved and provide them as locations to jump to. For example, using
'Go to Definition' on the `+` of `1 + 1` will yield results for
`HAdd.hAdd`, `HAdd α α α` and `Add Nat`.
- Using 'Go to Declaration' will now provide all the results of 'Go to
Definition' in addition to the elaborator and the parser that were
involved. For example, using 'Go to Declaration' on the `+` of `1 + 1`
will yield results for `HAdd.hAdd`, `HAdd α α α`, `Add Nat`,
``macro_rules | `($x + $y) => ...`` and `infixl:65 " + " => HAdd.hAdd`.
- Using 'Go to Type Definition' on a value with a type that contains
multiple constants will now provide 'Go to Definition' results for each
constant. For example, using 'Go to Type Definition' on `x` for `x :
Array Nat` will yield results for `Array` and `Nat`.

### Details
'Go to Definition' for type class projections was first implemented by
#1767, but there were still a couple of shortcomings with the
implementation. E.g. in order to jump to the instance in `toString 0`,
one had to add another space within the application and then use 'Go to
Definition' on that, or macros would block instances from being
displayed. Then, when the .ilean format was added, most 'Go to
Definition' requests were already handled using the .ileans in the
watchdog process, and so the file worker never received them to handle
them with the semantic information that it has available.

This PR resolves most of the issues with the previous implementation and
refactors the 'Go to Definition' control flow so that 'Go to Definition'
requests are always handled by the file worker, with the watchdog merely
using its .ilean position information to update the positions in the
response to a more up-to-date state. This is necessary because the file
worker obtains its position information from the .oleans, which need to
be rebuilt in order to be up-to-date, while the watchdog always receives
.ilean update notifications from each active file worker with the
current position information in the editor.

Finally, all of the 'Go to Definition' code is refactored to be easier
to maintain.

### Breaking changes
`InfoTree.hoverableInfoAt?` has been generalized to
`InfoTree.hoverableInfoAtM?` and now takes a general `filter` argument
instead of several boolean flags, as was the case before.
2025-07-21 15:47:44 +00:00
Lean stage0 autoupdater
51ae98ae30 chore: update stage0 2025-07-21 14:40:51 +00:00
Henrik Böving
09de5cd70e refactor: remove Lean.RBMap usages (#9260)
This PR removes uses of `Lean.RBMap` in Lean itself.

Furthermore some massaging of the import graph is done in order to avoid
having `Std.Data.TreeMap.AdditionalOperations` (which is quite
expensive) be the critical path for a large chunk of Lean. In particular
we can build `Lean.Meta.Simp` and `Lean.Meta.Grind` without it thanks to
these changes.

We did previously not conduct this change as `Std.TreeMap` was not
outperforming `Lean.RBMap` yet, however this has changed with the new
code generator.
2025-07-21 14:04:45 +00:00
Joachim Breitner
23e88b4e1d chore: test for issue #9018 (#9452) 2025-07-21 13:55:36 +00:00
Joachim Breitner
fcd60e73f8 fix: use withIncRecDepth in SizeOf deriving (#9448)
This PR addresses the lean crash (stack overflow) with nested induction
and the generation of the `SizeOf` spec lemmas, reported at #9018.

It does not address the underlying issue that in these cases, the
generated SizeOf code does not match the the SizeOf function found by
instance search, and thus the generation fails.

This seem hard to fix: `mkSizeOfMinors` would have to recognize that
given, say, `List (Id Tree)`, the derived instance (assuming there was
one for `Tree`) is not the same as for `List Tree`.

The problem seems just about as hard as getting derived SizeOf right in
the presence of nested induction and non-canonical SizeOf instances.
2025-07-21 12:43:19 +00:00
Rob23oba
b7f433c5b9 fix: behavior of String.prev (#9441)
This PR fixes the behavior of `String.prev`, aligning the runtime
implementation with the reference implementation. In particular, the
following statements hold now:
- `(s.prev p).byteIdx` is at least `p.byteIdx - 4` and at most
`p.byteIdx - 1`
- `s.prev 0 = 0`
- `s.prev` is monotone

Closes #9439
2025-07-21 10:50:14 +00:00
Sebastian Graf
f3ac38ff2c fix: Close pure, trivial goals in mvcgen (#9362) (#9447)
This PR ensures that `mvcgen` not only tries to close stateful subgoals
by assumption, but also pure Lean goals.

Closes #9362.
2025-07-21 10:12:34 +00:00
Lean stage0 autoupdater
c5a5c5572f chore: update stage0 2025-07-21 05:32:04 +00:00
Cameron Zwarich
2f7c0366f5 perf: treat partial application and eta expansion equally for specialization (#9438) 2025-07-20 14:57:21 +00:00
Cameron Zwarich
1a9757d1f6 refactor: make withReader calls more readable (#9442) 2025-07-20 13:39:35 +00:00
Mac Malone
3aaa3beeee feat: lake: job count in build success message (#9436)
This PR adds the number of jobs run to the final message Lake produces
on a successfully run of `lake build`.


**Examples**
```
Build completed successfully (1 job).
Build completed successfully (6 jobs).
```
2025-07-19 04:59:39 +00:00
Mac Malone
deef4e8e23 feat: lake: libPrefixOnWindows (#9435)
This PR adds the `libPrefixOnWindows` package and library configuration
option. When enabled, Lake will prefix static and shared libraries with
`lib` on Windows (i.e., the same way it does on Unix).
2025-07-19 04:46:42 +00:00
Mac Malone
c660f63748 refactor: lake: restore libs & exes from cache (#9434)
This PR changes the Lake local cache infrastructure to restore
executables and shared and static libraries from the cache. This means
they keep their expected names, which some use cases still rely on.
2025-07-19 03:28:42 +00:00
jrr6
b7e220039f feat: add hints for tuple projections (#9387)
This PR adds a hint to the "invalid projection" message suggesting the
correct nested projection for expressions of the form `t.n` where `t` is
a tuple and `n > 2`.

This feature was originally proposed by @nomeata in #8986.
2025-07-18 23:55:13 +00:00
jrr6
34bd6e8bfd feat: improve split error messages (#9424)
This PR improves the error messages produced by the `split` tactic,
including suggesting syntax fixes and related tactics with which it
might be confused.

Note that, to avoid clashing with the new error message styling
conventions used in these messages, this PR also updates the formatting
of the message produced by `throwTacticEx`.

Closes #6224
2025-07-18 22:36:10 +00:00
Cameron Zwarich
5cd5885da4 fix: make IRType.erased a tobject when boxing it (#9431)
This PR changes `IRType.boxed` to map `erased` to `tobject` rather than
`object`, since `erased` has a representation of a boxed scalar 0 when
we are forced to represent it at runtime. This case does not occur at
all in the Lean codebase.
2025-07-18 20:10:52 +00:00
jrr6
5f4e6a86d5 feat: update and explain "unknown constant" and "failed to infer type" errors (#9423)
This PR updates the formatting of, and adds explanations for, "unknown
identifier" errors as well as "failed to infer type" errors for binders
and definitions.

It attempts to ameliorate some of the confusion encountered in #1592 by
modifying the wording of the "header is elaborated before body is
processed" note and adding further discussion and examples of this
behavior in the corresponding error explanation.
2025-07-18 19:20:31 +00:00
Cameron Zwarich
1043569648 perf: use more precise IR types for overapplication (#9428) 2025-07-18 16:34:19 +00:00
Paul Reichert
383256defa chore: reintroduce Subarray.foldl on top of Slice.foldl (#9234)
An earlier PR (#9017) replaced certain subarray functions such as
`Subarray.foldl` with generic slice functions `Slice.foldl`. For
backward compatibility reasons, This PR reintroduces `Subarray.foldl`
etc. as aliases for the `Slice` versions.
2025-07-18 15:23:50 +00:00
Cameron Zwarich
cdab726e3d refactor: clean up creation of IR over-application (#9426) 2025-07-18 06:11:06 +00:00
Mac Malone
7b9ead4a1a chore: lake: module system tests & fixes (#9422)
This PR adds Lake tests for builds involving the Lean module system and
fixes some bugs encountered in the process. In particular, it fixes the
parsing of private imports and how Lake handles the `import all` of a
private import.
2025-07-18 02:34:13 +00:00
jrr6
6e191720b3 fix: open error explanations in new window in web editor (#9421)
This PR fixes a bug that caused error explanations to "steal" the
Infoview's container in the Lean web editor.
2025-07-17 23:20:35 +00:00
Sebastian Ullrich
9fc31abb1f chore: benchmark using USE_LAKE (#9361) 2025-07-17 18:44:29 +00:00
Markus Himmel
3878d6da85 chore: Grove: bump version (#9419) 2025-07-17 15:02:17 +00:00
Henrik Böving
097952c48f perf: simp subexpr benchmark (#9404)
This PR adds a simp benchmark to our suite, specifically targeting
caching of subexpression
rewriting results.
2025-07-17 11:53:48 +00:00
Sebastian Ullrich
e5730e9b7e refactor: module-ize remainder of Std (#9195) 2025-07-17 11:43:57 +00:00
Sebastian Ullrich
49546687d9 chore: update stage0 2025-07-17 11:54:06 +02:00
Sebastian Ullrich
2c08280854 fix: meta def should never be exposed (#9415) 2025-07-17 11:52:32 +02:00
Mac Malone
ebe68faf7f fix: lake: test script bugs w/ Mathlib & non-Linux (#9397)
This PR fixes some issues with the Lake tests on Windows and macOS. It
also avoids downloading Mathlib in the `init` test, which was currently
doing this after changes to the `math-lax` template in #8866.

To skip the Mathlib download in `init`, an undocumented `--offline`
option was added`. This option is currently meant for internal use only.
2025-07-17 07:08:00 +00:00
Leonardo de Moura
65abbd90bf perf: isArrowProposition (#9414)
This PR increases the number of cases where `isArrowProposition` returns
a result other than `.undef`. This function is used to implement the
`isProof` predicate, which is invoked on every subterm visited by
`simp`.
2025-07-17 04:12:15 +00:00
jrr6
119854e248 feat: add hints for missing structure instance fields (#9317)
This PR adds to the "fields missing" error message for structure
instance notation a code-action hint that inserts all missing fields.
2025-07-17 03:22:34 +00:00
jrr6
442ef6e64c feat: add case name hints (#9316)
This PR adds clickable code-action hints to the "invalid case name"
error message.
2025-07-17 03:22:30 +00:00
jrr6
fb462fdf9e feat: add named argument hints (#9315)
This PR adds improves the "invalid named argument" error message in
function applications and match patterns by providing clickable hints
with valid argument names. In so doing, it also fixes an issue where
this error message would erroneously flag valid match-pattern argument
names.
2025-07-17 03:22:25 +00:00
Cameron Zwarich
d667522524 refactor: remove special cases for subsingleton casesOn (#9412) 2025-07-16 23:41:41 +00:00
Cameron Zwarich
c1b5d54737 feat: compiler support for casesOn of subsingletons (#9411)
This PR adds support for compilation of `casesOn` for subsingletons. We
rely on the elaborator's type checking to restrict this to inductives in
`Prop` that can actually eliminate into `Type n`. This does not yet
cover other recursors of these types (or of inductives not in `Prop` for
that matter).
2025-07-16 23:07:32 +00:00
Sebastian Ullrich
f94d7b333a fix: do not export private instances (#9407)
Fixes #9383
2025-07-16 18:59:48 +00:00
Leonardo de Moura
d7ef2880c8 perf: avoid "dependent implications" as local E-matching theorems in grind (#9408)
This PR implements a simple optimization: dependent implications are no
longer treated as E-matching theorems in `grind`. In
`grind_bitvec2.lean`, this change saves around 3 seconds, as many
dependent implications are generated. Example:
```lean
 ∀ (h : i + 1 ≤ w), x.abs.getLsbD i = x.abs[i]
 ```
2025-07-16 17:13:52 +00:00
Sebastian Ullrich
f3944a3d49 chore: fix test 2025-07-16 17:51:42 +02:00
Sebastian Ullrich
263a77fa89 chore: update stage0 2025-07-16 16:04:47 +02:00
Sebastian Ullrich
2584b6abf9 fix: assorted module system fixes (#9406)
Encountered when porting `Std` and `Lean`
2025-07-16 13:31:08 +00:00
Markus Himmel
ca9b804163 chore: ci: specify which Linux toolchain Grove should download (#9405)
Since the old version of the workflow will run on PRs, we'll have to
"test" this on master.
2025-07-16 13:15:13 +00:00
Henrik Böving
e9ccdeecd0 perf: add a benchmark for simp on local hypotheses (#9403)
This PR adds a benchmark to our suite, specifically targeting the fact
that local hypotheses
are currently not indexed in simp and can thus cause significant
slowdowns compared to having them
as external declarations.
2025-07-16 12:16:29 +00:00
Sebastian Ullrich
2ed4f39ffe chore: adapt core to preceding syntax change 2025-07-16 13:32:11 +02:00
Sebastian Ullrich
1959e6088b chore: update stage0 2025-07-16 13:32:11 +02:00
Sebastian Ullrich
ffbb21a032 fix: order of @[expose] public section
This PR makes the order of `@[expose] public` at `section` consistent with that at `def`
2025-07-16 13:32:11 +02:00
Sebastian Ullrich
e088549330 refactor: module-ize Std.Time (#9100) 2025-07-16 09:57:53 +00:00
Mac Malone
587979341a refactor: lake: optimize module build code for new compiler (#9400)
This PR splits up `Module.recBuildLean` into smaller functions and
optimizes the implementation of `Module.cacheOutputArtifacts` for the
new compiler. Now, all functions within `Lake.Build.Module` take Lean
<1s to compile.
2025-07-16 07:27:34 +00:00
Mac Malone
180bfeaba4 feat: lake: pre-resolve module imports (#9053)
This PR updates Lake to resolve the `.olean` files for transitive
imports for Lean through the `modules` field of `lean --setup`. This
enables means the Lean can now directly use the `.olean` files from the
Lake cache without needed to locate them at a specific hierarchical
path.

Resolving transitive imports still has a performance penalty, but it is
now much less.
2025-07-16 04:21:31 +00:00
Lean stage0 autoupdater
e6cce355e3 chore: update stage0 2025-07-16 04:26:10 +00:00
Cameron Zwarich
e9b75e34b7 perf: decide whether to use _ref variants of inc/dec using IR types (#9399) 2025-07-16 03:52:58 +00:00
Leonardo de Moura
e286f20179 perf: avoid inferType at simpArith (#9398)
This PR avoids the expensive `inferType` call in `simpArith`. It also
cleans up some of the code and removes anti-patterns.
2025-07-16 03:42:26 +00:00
Lean stage0 autoupdater
d4afa3caaa chore: update stage0 2025-07-16 02:48:16 +00:00
Cameron Zwarich
e069c9eb0e perf: use IR type info to decide whether to insert RC ops (#9396)
This is mostly a refactoring that replaces other analyses with type
information, but due to the introduction of `tagged` it also has the
side effect of eliminating ref counting ops entirely for types that
always have a tagged scalar representation, e.g. `Unit`.
2025-07-16 02:02:32 +00:00
Leonardo de Moura
dc2f256448 fix: bug at mkCongrSimpCore? (#9395)
This PR fixes a bug at `mkCongrSimpCore?`. It fixes the issue reported
by @joehendrix at #9388.
The fix is just commit: afc4ba617f. The
rest of the PR is just cleaning up the file.

closes #9388
2025-07-16 00:54:31 +00:00
Cameron Zwarich
62ded77e81 chore: add a new tagged IRType for inline tagged scalars (#9394) 2025-07-16 00:42:56 +00:00
Cameron Zwarich
466e8a6c5e fix: adjust unsafe trick for upcoming optimization (#9393)
This PR fixes an unsafe trick where a sentinel for a hash table of Exprs
(keyed by pointer) is created by constructing a value whose runtime
representation can never be a valid Expr. The value chosen for this
purpose was Unit.unit, which violates the inference that Expr has no
scalar constructors. Instead, we change this to a freshly allocated Unit
× Unit value.
2025-07-16 00:10:01 +00:00
Cameron Zwarich
b131e8b97f chore: adopt tobject IRType (#9392) 2025-07-15 23:56:49 +00:00
Cameron Zwarich
d7ef2a8d1c refactor: add a CtorFieldInfo.object field for the object type (#9390) 2025-07-15 23:18:23 +00:00
jrr6
3b58a7d36b fix: improve error message when projecting from zero-field type (#9386)
This PR improves a confusing error message that occurred when attempting
to project from a zero-field structure.

Closes #9312
2025-07-15 21:32:59 +00:00
jrr6
e9a318df16 fix: reorder "application type mismatch" message (#9287)
This PR rewords the "application type mismatch" error message so that
the argument and its type precede the application expression.
2025-07-15 19:20:18 +00:00
Leonardo de Moura
166d1c0dab perf: avoid isDefEq test at simpEq simproc used in grind (#9385)
This PR replaces the `isDefEq` test in the `simpEq` simproc used in
`grind`. It is too expensive.
2025-07-15 18:38:11 +00:00
Joachim Breitner
0926d27100 chore: fix benchmark added in #9380 (#9384) 2025-07-15 18:24:34 +00:00
Henrik Böving
aa6f22d102 chore: reduce import closure of MPL (#9382)
This PR reduces the import closure of the monadic verification framework
from `Lean.Meta` to only
the submodules actually required.
2025-07-15 16:36:03 +00:00
Joachim Breitner
6adeab2160 chore: add simple simp benchmark (#9380)
A micro-benchmark for plain, mostly first-order rewriting of simp:

This uses axiom to make it independent of specific optimization (e.g.
for `Nat`).

It generates a “list” of 128 `b`s followed by 128 `a` and uses
bubble-sort to to sort it and compares it against the expected output.
2025-07-15 15:04:49 +00:00
Malhar A. Patel
6cbdd6b815 doc: correct the Option.getD docString example (#9190)
This PR corrects the second example in the `Option.getD` docString

Closes #9189
2025-07-15 12:39:58 +00:00
Henrik Böving
a8c0348300 chore: re-simp Std.LawfulEqCmp.compare_eq_iff_eq (#9377)
This PR readds `simp` annotations accidentally lost in previous PRs
2025-07-15 12:10:50 +00:00
Filippo A. E. Nuccio
08d8bed022 doc: fix a typo in Pairwise doc (#9375)
doc: fix a typo in Pairwise doc

This PR fixes a sentence in the Pairwise doc in List/Basic
2025-07-15 11:39:02 +00:00
Henrik Böving
6e9bc1359d fix: don't delay lake logging when cloning a dependency (#9332)
This PR changes the dependency cloning mechanism in lake so the log
message that lake is cloning a
dependency occurs before it is finished doing so (and instead before it
starts). This has been a
huge source of confusion for users that don't understand why lake seems
to be just stuck for no
reason when setting up a new project, the output now is:
```
λ lake +lean4 new math math
info: downloading mathlib `lean-toolchain` file
info: math: no previous manifest, creating one from scratch
info: leanprover-community/mathlib: cloning https://github.com/leanprover-community/mathlib4
<hang>
info: leanprover-community/mathlib: checking out revision 'cd11c28c6a0d514a41dd7be9a862a9c8815f8599'
```
2025-07-15 09:38:35 +00:00
Cameron Zwarich
aac501a645 refactor: split up mkExpr helper in lowerLet (#9374) 2025-07-15 05:26:21 +00:00
Cameron Zwarich
cf94e1b162 refactor: get the type of a literal from lowerLitValue (#9373)
This will let us have value-dependent types in the future for tracking
tagged/boxed values.
2025-07-15 04:46:47 +00:00
Leonardo de Moura
96e7ab078d fix: performance issue when elaborating match-expressions with many literals (#9372)
This PR fixes a performance issue that occurs when generating equation
lemmas for functions that use match-expressions containing several
literals. This issue was exposed by #9322 and arises from a combination
of factors:

1. Literal values are compiled into a chain of dependent if-then-else
expressions.
2. Dependent if-then-else expressions are significantly more expensive
to simplify than regular ones.
3. The `split` tactic selects a target, splits it, and then invokes
`simp` on the resulting subgoals. Moreover, `simp` traverses the entire
goal bottom-up and does not stop after reaching the target.

This PR addresses the issue by introducing a custom simproc that avoids
recursively simplifying nested if-then-else expressions. It does **not**
alter the user-facing behavior of the `split` tactic because such a
change would be highly disruptive. Instead, the PR adds a new flag,
`backward.split` to control the behavior of the user-facing `split`
tactic. It is currently set to `true`, i.e., the old behavior is still
the default one. In a future PR, we should set this flag to `false` by
default and begin repairing all affected proofs.

closes #9322
2025-07-15 03:52:23 +00:00
Cameron Zwarich
9d33f2ad33 chore: make IR.Arg pattern matching more exhaustive (#9370) 2025-07-14 22:46:40 +00:00
Leonardo de Moura
a4b5eecb8e perf: skip unnecessary preprocessing steps in grind when possible (#9369)
This PR optimizes the `grind` preprocessor by skipping unnecessary steps
when possible.
2025-07-14 22:05:02 +00:00
Cameron Zwarich
f224452971 chore: simplify box/unbox casting logic (#9368) 2025-07-14 21:51:09 +00:00
Sebastian Ullrich
caf815b009 feat: improve infer binder type failure message and range (#8263)
This PR improves the message and range of infer binder type failures.

---------

Co-authored-by: Joseph Rotella <7482866+jrr6@users.noreply.github.com>
2025-07-14 20:19:11 +00:00
Cameron Zwarich
c0079fd9dd perf: allow boxed scalars passed to scalar params to be borrowed (#9360) 2025-07-14 19:58:01 +00:00
Leonardo de Moura
cfb13b1689 perf: add unfoldReducible' using inShareCommon (#9367)
This PR implements a minor optimization to the `grind` preprocessor.
2025-07-14 19:04:04 +00:00
jrr6
105843519c doc: expand elab_as_elim docstring and fix typo (#9359)
This PR adds additional information from a recent Zulip thread to the
docstring for the `elab_as_elim` attribute and fixes the associated
example code.

The Zulip thread can be found
[here](https://leanprover.zulipchat.com/#narrow/channel/113488-general/topic/what.20is.20.60elab_as_elim.60/with/505631084).
2025-07-14 17:53:42 +00:00
Sebastian Ullrich
97698bfc38 chore: CI: use faster Windows runners for releases (#9357) 2025-07-14 16:26:22 +00:00
Sebastian Ullrich
7f1869016a chore: CI: do not use large runners for secondary jobs (#9352)
macOS in particular is expensive to use large machines for more than
necessary
2025-07-14 15:00:58 +00:00
Markus Himmel
0931033c72 chore: Grove: add some data (#9354) 2025-07-14 10:22:59 +00:00
Markus Himmel
a7789d863c chore: Grove: update and enable on master (#9353) 2025-07-14 09:21:51 +00:00
Leonardo de Moura
bcc6fb54c2 perf: use inShareCommon to skip preprocessing steps (#9351)
This PR optimizes the `grind` preprocessing steps by skipping steps when
the term is already present in the hash-consing table.
2025-07-14 04:53:49 +00:00
Cameron Zwarich
b04ee0de57 chore: remove outdated comments (#9349) 2025-07-14 01:15:36 +00:00
Cameron Zwarich
7a83adf10d refactor: rename mmodifyBody functions to modifyBodyM (#9348) 2025-07-14 01:01:46 +00:00
Leonardo de Moura
d642880b7d chore: remove leftovers (#9347)
after update stage0
2025-07-14 00:40:32 +00:00
Lean stage0 autoupdater
74206c755f chore: update stage0 2025-07-14 00:11:34 +00:00
Leonardo de Moura
c7b4d843e2 refactor: support for Nat in grind cutsat (#9340)
This PR modifies the encoding from `Nat` to `Int` used in `grind
cutsat`. It is simpler, more extensible, and similar to the generic
`ToInt`. After update stage0, we will be able to delete the leftovers.
2025-07-13 23:40:03 +00:00
Cameron Zwarich
c90cc392f7 fix: populate the xType field of FnBody.case (#9344)
This PR correctly populates the `xType` field of the `IR.FnBody.case`
constructor. It turns out that there is no obvious consequence for this
being incorrect, because it is conservatively recomputed by the `Boxing`
pass.
2025-07-13 21:56:07 +00:00
Leonardo de Moura
f298360ff9 refactor: more "efficient" contraint propagation theorems (#9343)
The certificates perform a single pass over the polynomials.
2025-07-13 19:52:43 +00:00
Leni Aniva
275e483885 refactor: Expose DeclNameGenerator idx (#9020)
This PR exposes the internal of DeclNameGenerator to facilitate merger
of two branches of goal state or proof snapshots.
2025-07-13 10:24:04 +00:00
Cameron Zwarich
e87ce2bd5b refactor: rename "irrelevant" to "erased" in IR (#9339)
This matches the terminology used by LCNF.
2025-07-13 04:51:34 +00:00
Cameron Zwarich
3c6a923f1b refactor: use the usize index in the CtorFieldInfo struct (#9337) 2025-07-13 03:05:13 +00:00
Cameron Zwarich
b25ef7682d chore: fix spacing (#9338) 2025-07-13 03:03:50 +00:00
Cameron Zwarich
71b5bf3ef6 fix: include ._closed decls in trace.Compiler.result output (#9336)
This PR changes the implementation of `trace.Compiler.result` to use the
decls as they are provided rather than looking them up in the LCNF mono
environment extension, which was seemingly done to save the trouble of
re-normalizing fvar IDs before printing the decl. This means that the
`._closed` decls created by the `extractClosed` pass will now be
included in the output, which was definitely confusing before if you
didn't know what was happening.
2025-07-13 02:24:00 +00:00
jrr6
8dfc71c4fd chore: remove superfluous whitespace from error message (#9335)
This PR fixes a typo that caused the "cannot infer resulting universe
level of inductive datatype" error message to have leading whitespace.
2025-07-12 23:04:02 +00:00
Leonardo de Moura
243bbd74a5 chore: compilation time for EMatch.lean (#9334)
This PR improves the compilation time for `EMatch.lean`
2025-07-12 22:01:16 +00:00
Cameron Zwarich
aba49508f1 refactor: port IR Checker to CompilerM (and thus CoreM) (#9331) 2025-07-12 15:25:46 +00:00
Leonardo de Moura
ae2a9b4688 perf: propagateEqUp (#9326)
This PR optimizes `propagateEqUp` used in `grind`.
2025-07-12 03:09:59 +00:00
Leonardo de Moura
d36fc8df67 perf: propagateBoolDiseq (#9325)
This PR optimizes the Boolean disequality propagator used in `grind`.
2025-07-12 02:20:48 +00:00
Leonardo de Moura
6c20cd08f1 perf: isDiseq and mkDiseqProof? in grind (#9324)
This PR improves the functions for checking whether two terms are
disequal in `grind`
2025-07-12 01:26:48 +00:00
Cameron Zwarich
46b04c8405 chore: lower Nat.zero in toMono (#9320)
This currently relies on the encoding pun of Nat.zero as the first
tagged constructor of Nat. Since Nat.succ is lowered to addition, it
makes sense to also lower Nat.zero to a zero literal. This might also
expose more optimization opportunities in the future.
2025-07-11 23:25:05 +00:00
Cameron Zwarich
efc101d3b4 chore: move Nat.succ lowering from toIR to toMono (#9319)
It makes more sense to do it here, since `cases` on `Nat` is also
lowered in `toMono`.
2025-07-11 22:49:41 +00:00
Cameron Zwarich
e2e36087e1 refactor: split noncomputable error into its own helper (#9314) 2025-07-11 17:30:22 +00:00
Cameron Zwarich
d4e11f754a chore: clean up loop over ctor fields (#9313) 2025-07-11 16:46:48 +00:00
Cameron Zwarich
837ea41ede fix: correctly compile irrelevant args to relevant ctor params (#9310)
This PR fixes IR constructor argument lowering to correctly handle an
irrelevant argument being passed for a relevant parameter in all cases.
This happened because constructor argument lowering (incompletely)
reimplemented general LCNF-to-IR argument lowering, and the fix is to
just adopt the generic helper functions. This is probably due to an
incomplete refactoring when the new compiler was still on a branch.
2025-07-11 15:29:12 +00:00
simon-dima
5778a3c0f2 chore: fix "isRuntimeBultinType" typo (#9307) 2025-07-11 12:27:07 +00:00
Lean stage0 autoupdater
668a892cdb chore: update stage0 2025-07-11 08:18:55 +00:00
Leonardo de Moura
0fdb63f258 perf: use mkCongrSimpForConst? (#9305)
This PR uses the `mkCongrSimpForConst?` API in `simp` to reduce the
number of times the same congruence lemma is generated. Before this PR,
`grind` would spend `1.5`s creating congruence theorems during
normalization in the `grind_bitvec2.lean` benchmark. It now spends
`0.6`s. This PR should make an even bigger difference after we merge
#9300.
2025-07-11 02:29:20 +00:00
Sebastian Graf
338456e765 feat: help simp and grind reasoning about Std.Do invariants (#9301)
This PR adds a `simp` and a `grind` annotation on `Zipper`-related
theorems to improve reasoning about `Std.Do` invariants.
2025-07-10 15:44:29 +00:00
Tasiro
18a82c04fc fix: remove BEq from (Array|Vector).(any|all)_push (#9285)
This PR removes the unnecessary requirement of `BEq α` for
`Array.any_push`, `Array.any_push'`, `Array.all_push`, `Array.all_push'`
as well as `Vector.any_push` and `Vector.all_push`.
2025-07-10 06:02:14 +00:00
Leonardo de Moura
4520206f4a chore: minor perf improvement (#9296) 2025-07-10 05:41:54 +00:00
Cameron Zwarich
9ee8e0c896 chore: remove outdated comment (#9294) 2025-07-10 03:29:22 +00:00
Leonardo de Moura
62dc8d64fa perf: use custom reduceCtorEq simproc in grind (#9293)
This PR replaces the `reduceCtorEq` simproc used in `grind` by a much
more efficient one. The default one use in `simp` is just overhead
because the `grind` normalizer is already normalizing arithmetic.
In a separate PR, we will push performance improvements to the default
`reduceCtorEq`.
2025-07-10 03:18:44 +00:00
Cameron Zwarich
7845154a3d refactor: base the IR phase of the compiler on CoreM (#9291) 2025-07-10 01:39:27 +00:00
Cameron Zwarich
66de09bc9c refactor: use getEnv/modifyEnv more in IR (#9290) 2025-07-10 00:01:56 +00:00
Cameron Zwarich
3e37eef9ea refactor: remove unused addBoxedVersion variants (#9289) 2025-07-09 23:44:18 +00:00
Cameron Zwarich
d3a4bb29a7 chore: remove comment indicating that implicit conversion should be removed (#9284) 2025-07-09 17:31:34 +00:00
Cameron Zwarich
1db5e35b59 chore: remove ABI hack for the old compiler (#9283) 2025-07-09 17:25:38 +00:00
Cameron Zwarich
efe5e9a752 refactor: remove unnecessary export attributes (#9281) 2025-07-09 16:55:00 +00:00
Cameron Zwarich
a4f38cc782 refactor: remove code marked for deletion after old compiler (#9280) 2025-07-09 15:30:11 +00:00
Cameron Zwarich
b579c5c7d8 fix: make compiler.extract_closed option work again after migration (#9279)
This PR fixes the `compiler.extract_closed` option after migrating it to
Lean (and adds a test so it would be caught in the future).
2025-07-09 14:31:58 +00:00
Cameron Zwarich
575adbae18 chore: remove now-unused Lean.Compiler.AtMostOnce (#9278) 2025-07-09 14:31:15 +00:00
Cameron Zwarich
5e19c47710 chore: remove now-unused Lean.Compiler.ConstFolding (#9277) 2025-07-09 14:18:32 +00:00
Cameron Zwarich
a7675ad4b2 chore: remove unnecessary export attributes in IR code (#9276) 2025-07-09 14:18:07 +00:00
Cameron Zwarich
d2e604f74d feat: remove the old compiler (#9275)
This PR removes the old compiler written in C++.
2025-07-09 06:00:46 +00:00
Chase Johnson
4c93ab7602 fix: typos in ISO 8601 formatted datetime (#9235) (#9263)
This PR fixes `toISO8601String` to produce a string that conforms to the
ISO 8601 format specification. The previous implementation separated the
minutes and seconds fragments with a `.` instead of a `:` and included
timezone offsets without the hour and minute fragments separated by a
`:`.

Closes #9235
2025-07-09 05:52:25 +00:00
Cameron Zwarich
625de14b23 chore: remove options from 'run' tests that are now meaningless (#9274) 2025-07-09 05:26:58 +00:00
Cameron Zwarich
b13b916b7e chore: move compiler.ir trace class registration to Lean (#9273) 2025-07-09 05:15:38 +00:00
Cameron Zwarich
9f2b796639 chore: move compiler.extract_closed option from C++ to Lean (#9272) 2025-07-09 04:36:16 +00:00
Leonardo de Moura
4955dde748 perf: grind normalizer (#9271)
This PR improves the performance of the formula normalizer used in
`grind`.
2025-07-09 03:49:44 +00:00
Cameron Zwarich
3b18ae2209 chore: move llvm.cpp from library/compiler to library (#9270) 2025-07-09 02:13:08 +00:00
Cameron Zwarich
9620cb1b90 chore: have shell.cpp use library/util.h rather than library/compiler… (#9269) 2025-07-09 01:41:04 +00:00
Cameron Zwarich
d664b6b888 fix: move lean_add_extern implementation to Lean (#9268)
This PR moves the implementation of `lean_add_extern`/`addExtern` from
C++ into Lean. I believe is the last C++ helper function from the
library/compiler directory being relied upon by the new compiler. I put
it into its own file and duplicated some code because this function
needs to execute in CoreM, whereas the other IR functions live in their
own monad stack. After the C++ compiler is removed, we can move the IR
functions into CoreM.
2025-07-09 00:02:56 +00:00
Leonardo de Moura
192c0c8e67 perf: skip canonicalization of Decidable instances and add congruence-closure support (#9267)
This PR optimizes support for `Decidable` instances in `grind`. Because
`Decidable` is a subsingleton, the canonicalizer no longer wastes time
normalizing such instances, a significant performance bottleneck in
benchmarks like `grind_bitvec2.lean`. In addition, the
congruence-closure module now handles `Decidable` instances, and can
solve examples such as:
```lean
example (p q : Prop) (h₁ : Decidable p) (h₂ : Decidable (p ∧ q)) : (p ↔ q) → h₁ ≍ h₂ := by
  grind
```
2025-07-08 21:55:40 +00:00
Cameron Zwarich
cec0c82f1c fix: support .mdata in LCNF mono types (#9266)
This PR adds support for `.mdata` in LCNF mono types (and then drops it
at the IR type level instead). This better matches the behavior of
extern decls in the C++ code of the old compiler, which is still being
used to create extern decls at the moment and will soon be replaced.

This is covered by existing tests.
2025-07-08 21:35:30 +00:00
Cameron Zwarich
4ff4ed88bc chore: move the IR interpreter from library/compiler to library (#9265) 2025-07-08 20:45:55 +00:00
Cameron Zwarich
a05311d1ec chore: split IR types out into their own header file (#9264) 2025-07-08 19:49:27 +00:00
Cameron Zwarich
f675ee2062 chore: remove unnecessary include of ir_interpreter.h (#9262) 2025-07-08 18:09:20 +00:00
Cameron Zwarich
cb127b42ac chore: rename compileDeclsNew to compileDeclsImpl (#9261) 2025-07-08 17:55:11 +00:00
Cameron Zwarich
c7c5de38b3 chore: clean up getDeclNamesForCodeGen (#9259) 2025-07-08 17:00:46 +00:00
Cameron Zwarich
6ad12525ad chore: make compileDecls and friends take an Array rather than a List (#9257) 2025-07-08 16:18:44 +00:00
Cameron Zwarich
bb5df157bc chore: remove unused optional parameter from compileDecls (#9255) 2025-07-08 15:31:06 +00:00
Sebastian Graf
77442f5486 chore: revert DefEq changes until it has passed proper review (#9254) 2025-07-08 14:54:18 +00:00
Hagb (Junyu Guo 郭俊余)
97aca690d0 fix: walk through types of axioms in collectAxioms (#8842)
This PR fixes the bug that `collectAxioms` didn't collect axioms
referenced by other axioms. One of the results of this bug is that
axioms collected from a theorem proved by `native_decide` may not
include `Lean.trustCompiler`.

Closes #8840.
2025-07-08 14:42:11 +00:00
Cameron Zwarich
173629ebd5 chore: remove compiler.enableNew option (#9252) 2025-07-08 14:17:05 +00:00
Cameron Zwarich
beeeead99f chore: remove mentions of the compiler being new from trace messages (#9253) 2025-07-08 14:15:15 +00:00
Lean stage0 autoupdater
d38c36001d chore: update stage0 2025-07-08 14:35:54 +00:00
Sebastian Graf
7386cc3b12 chore: Turn Std.Do.Triple elaborator into a macro (#9251)
This PR demotes the builtin elaborators for `Std.Do.PostCond.total` and
`Std.Do.Triple` into macros, following the DefEq improvements of #9015.

Co-authored-by: Sebastian Graf <sg@lean-fro.org>
2025-07-08 13:57:22 +00:00
Henrik Böving
7958e01b1c perf: basic micro benchmarks for Std.Data.TreeMap (#9250)
This PR adds micro-benchmarks for `Std.Data.TreeMap` in the same style
as for the hashmap.
2025-07-08 13:55:13 +00:00
Lean stage0 autoupdater
47e8483b38 chore: update stage0 2025-07-08 13:35:02 +00:00
Sebastian Graf
0b2bdaebd6 fix: More stuck definitional equalities involving smart unfoldings (#8766) (#9015)
This PR makes `isDefEq` detect more stuck definitional equalities
involving smart unfoldings. Specifically, if `t =?= defn ?m` and `defn`
matches on its argument, then this equality is stuck on `?m`. Prior to
this change, we would not see this dependency and simply return `false`.

Fixes #8766.

Co-authored-by: Kyle Miller <kmill31415@gmail.com>
2025-07-08 12:56:50 +00:00
Kyle Miller
ac600853c0 fix: let the congr tactic handle "under-applied" applications (#9225)
This PR improves the `congr` tactic so that it can handle function
applications with fewer arguments than the arity of the head function.
This also fixes a bug where `congr` could not make progress with
`Set`-valued functions in Mathlib, since `Set` was being unfolded and
making such functions have an apparently higher arity.

This addresses issue #2128 for the `congr` tactic, but not `simp` and
others.
2025-07-08 11:48:08 +00:00
Luisa Cicolini
77a0c2bf9b feat: add BitVec.clzAuxRec_eq_clzAuxRec_of_getLsbD_false (#9249)
This PR adds theorem `BitVec.clzAuxRec_eq_clzAuxRec_of_getLsbD_false` as
a more general statement than `BitVec.clzAuxRec_eq_clzAuxRec_of_le`,
replacing the latter in the bitblaster too.
2025-07-08 10:40:40 +00:00
Henrik Böving
46c43c3ecb perf: first set of HashMap benchmarks (#9233)
This PR adds basic microbenchmarks for `Std.Data.HashMap`
2025-07-08 08:11:52 +00:00
Cameron Zwarich
6de68dd8ef chore: remove compiler.enableNew=true from a test and rename it (#9247) 2025-07-08 05:49:57 +00:00
Cameron Zwarich
97fd75c660 chore: remove redundancy in toMono trivial structure check (#9245) 2025-07-08 05:07:16 +00:00
Leonardo de Moura
cf6a182f69 chore: profile grind satellite solvers (#9246) 2025-07-08 05:05:39 +00:00
Leonardo de Moura
655c7ab548 perf: optimize instance generation in grind linarith (#9244)
This PR improves the instance generation in the `grind linarith` module.
2025-07-08 05:04:06 +00:00
Cameron Zwarich
70368ed1a5 chore: reduce rightward drift (#9243) 2025-07-08 03:41:37 +00:00
Cameron Zwarich
765f98770b chore: improve pattern matching (#9242) 2025-07-08 03:36:34 +00:00
Leonardo de Moura
05630fc149 perf: synthesize ToInt instances on demand (#9241)
This PR ensures that the type class instances used to implement the
`ToInt` adapter (in `grind cutsat`) are generated on demand.
2025-07-08 02:36:16 +00:00
Cameron Zwarich
2d173615ba chore: remove unreachable branches (#9240)
There is a global `tryIrDecl?` check above all of this code.
2025-07-08 00:16:12 +00:00
Cameron Zwarich
b2920d6410 chore: consolidate noncomputable diagnostics (#9239) 2025-07-07 23:39:49 +00:00
Leonardo de Moura
aee2da809a chore: test for issue #9216 (#9238)
This PR adds a new test with the analysis for issue #9216.
2025-07-07 23:25:25 +00:00
Leonardo de Moura
2bf9130b63 chore: tests for #9206 (#9237)
Add examples in issue #9206 and Zulip thread as tests for `grind`.
2025-07-07 23:01:38 +00:00
Sebastian Graf
67d9d9d936 chore: Update CODEOWNERS (#9232)
Co-authored-by: Sebastian Graf <sg@lean-fro.org>
2025-07-07 13:11:41 +00:00
Sebastian Graf
0c5946ab3f feat: Make Std.Do universe polymorphic (#9194)
This PR makes the logic and tactics of `Std.Do` universe polymorphic, at
the cost of a few definitional properties arising from the switch from
`Prop` to `ULift Prop` in the base case `SPred []`.

Co-authored-by: Sebastian Graf <sg@lean-fro.org>
2025-07-07 13:11:41 +00:00
Paul Reichert
98e4b2882f refactor: migrate to new ranges (#8841)
This PR migrates usages of `Std.Range` to the new polymorphic ranges.

This PR unfortunately increases the transitive imports for
frequently-used parts of `Init` because the ranges now rely on iterators
in order to provide their functionality for types other than `Nat`.
However, iteration over ranges in compiled code is as efficient as
before in the examples I checked. This is because of a special
`IteratorLoop` implementation provided in the PR for this purpose.

There were two issues that were uncovered during migration:

* In `IndPredBelow.lean`, migrating the last remaining range causes
`compilerTest1.lean` to break. I have minimized the issue and came to
the conclusion it's a compiler bug. Therefore, I have not replaced said
old range usage yet (see #9186).
* In `BRecOn.lean`, we are publicly importing the ranges. Making this
import private should theoretically work, but there seems to be a
problem with the module system, causing the build to panic later in
`Init.Data.Grind.Poly` (see #9185).
* In `FuzzyMatching.lean`, inlining fails with the new ranges, which
would have led to significant slowdown. Therefore, I have not migrated
this file either.
2025-07-07 12:41:53 +00:00
Henrik Böving
6e98dfbc64 perf: bv_decide rewriting benchmark (#9231)
This PR adds a benchmark for the rewriting engine of bv_decide, based on
a problem extracted from
SMT-LIB. Note that this problem has significant elaboration time itself
due to its sheer size though
the overall execution time is split approximately 50:50 between
elaboration and rewriting.
2025-07-07 10:24:08 +00:00
Cameron Zwarich
e7e4119cf4 chore: move handling of Quot.{mk, lcInv} from toIR to toMono (#9230) 2025-07-07 05:11:23 +00:00
Cameron Zwarich
6cf8828ce7 chore: remove unused code in the axiom path of toIR (#9229)
This must have been the result of an earlier refactoring, since there
are no axioms with IR decls.
2025-07-07 03:45:39 +00:00
Leonardo de Moura
5d46391dde perf: generate grind ring instances on demand (#9228)
This PR improves the startup time for `grind ring` by generating the
required type classes on demand. This optimization is particularly
relevant for files that make hundreds of calls to `grind`, such as
`tests/lean/run/grind_bitvec2.lean`. For example, before this change,
`grind` spent 6.87 seconds synthesizing type classes, compared to 3.92
seconds after this PR.
2025-07-07 03:29:42 +00:00
Cameron Zwarich
c9debdaf2a chore: move lcUnreachable handling from toIR to toLCNF (#9227)
We can probably remove `lcUnreachable` once we delete the old compiler,
but for now it makes more sense to move it earlier, since LCNF already
has `Code.unreachable`.
2025-07-07 02:17:30 +00:00
Cameron Zwarich
9b7a14b156 fix: erase args for erased app params in toMono (#9224)
This PR changes the `toMono` pass to consider the type of an application
and erase all arguments corresponding to erased params. This enables a
lightweight form of relevance analysis by changing the mono type of a
decl. I would have liked to unify this with the behavior for
constructors, but my attempt to give constructors the same behavior in
#9222 (which was in preparation for this PR) had a minor performance
regression that is really incidental to the change. Still, I decided to
hold off on it for the time being. In the future, we can hopefully
extend this to constructors, extern decls, etc.
2025-07-06 23:27:48 +00:00
Cameron Zwarich
ff5d96096a chore: use Array instead of PArray in elimDeadBranches state (#9220)
This is alway used linearly.
2025-07-06 21:31:47 +00:00
Cameron Zwarich
53d4139cf1 chore: revert #9218 (#9223)
I thought I understood why the the minor !bench performance regression
was spurious, but now I'm not so sure.
2025-07-06 15:33:10 +00:00
Cameron Zwarich
c1f1287e24 fix: delete code with false assumption that LCNF local vars can occur in types (#9221)
This PR removes code that has the false assumption that LCNF local vars
can occur in types. There are other comments in `ElimDead.lean`
asserting that this is not possible, so this must have been a change
early in the development of the new compiler.
2025-07-06 15:04:13 +00:00
Cameron Zwarich
4322a0c7d3 fix: make LCNF elimDeadBranches more optimistic on unsafe decls (#9218)
This PR makes the LCNF `elimDeadBranches` pass handle unsafe decls a bit
more carefully. Now the result of an unsafe decl will only become ⊤ if
there is value flow from a recursive call.
2025-07-06 13:28:07 +00:00
Cameron Zwarich
d0e097cd1d chore: remove IRType.{isStruct,isUnion} (#9219)
These are used by the checker for `.ctor`, but I don't think that that
unboxed types will reuse `.ctor`, whose implementation details are
intimately connected to our runtime representation of objects.
2025-07-06 13:24:24 +00:00
Cameron Zwarich
bd7e6c3c61 chore: use ``-prefixed Names when possible (#9217) 2025-07-06 12:58:13 +00:00
Leonardo de Moura
1443982924 perf: restore cache at withoutModifyingMCtx (#9215)
instead of resetting it.
2025-07-06 04:18:37 +00:00
Leonardo de Moura
15586e28a8 feat: local and scoped grind_pattern (#9214)
This PR implements support for local and scoped `grind_pattern`
commands.
2025-07-05 20:36:56 -07:00
Cameron Zwarich
6f5fdf5c3e chore: adopt do notation in IR checker (#9213)
I plan to make some changes here in the future, so I figured it would be
good to make it a bit more idiomatic first.
2025-07-06 02:39:03 +00:00
Eric Wieser
bd06e07624 fix: make the name in dependsOnNoncomputable clickable (#9207)
This PR makes the offending declaration clickable in the error message
produced when something should be marked `noncomputable`.
2025-07-05 21:28:35 +00:00
Leonardo de Moura
2cf6c2ddc9 feat: track type class inference time in grind (#9211) 2025-07-05 20:24:32 +00:00
Cameron Zwarich
38d4dc7058 chore: add deriving Repr to IR.Arg (#9210)
This is helpful when debugging.
2025-07-05 19:57:41 +00:00
Cameron Zwarich
149fc2173c fix: correctly handle constructor params in elimDeadBranches (#9209)
This PR changes the `getLiteral` helper function of `elimDeadBranches`
to correctly handle inductives with constructors. This function is not
used as often as it could be, which makes this issue rare to hit outside
of targeted test cases.
2025-07-05 19:52:12 +00:00
Leonardo de Moura
12536d2015 chore: remove old grind normalizers (#9205) 2025-07-05 06:19:34 +00:00
Cameron Zwarich
36c036d952 chore: replace custom instances with deriving for IR types (#9204) 2025-07-05 05:43:07 +00:00
Lean stage0 autoupdater
bebffc0d20 chore: update stage0 2025-07-05 05:51:10 +00:00
Leonardo de Moura
dd7bc0e643 perf: simproc for grind normalizations and decls to unfold (#9202)
This PR extends the `Eq` simproc used in `grind`. It covers more cases
now. It also adds 3 reducible declarations to the list of declarations
to unfold.
2025-07-05 05:13:49 +00:00
Cameron Zwarich
264aac4a33 chore: convert local functions to use where instead (#9203) 2025-07-05 05:10:55 +00:00
Leonardo de Moura
d981a2a9a8 chore: remove old normalizers (#9201) 2025-07-05 02:43:00 +00:00
Lean stage0 autoupdater
2ca6c3bf4d chore: update stage0 2025-07-05 02:09:15 +00:00
Leonardo de Moura
722ab706c8 perf: normalize exists expressions using a simproc in grind (#9200)
This PR implements `exists` normalization using a simproc instead of
rewriting rules in grind. This is the first part of the PR, after update
stage0, we must remove the normalization theorems.
2025-07-05 01:37:36 +00:00
Lean stage0 autoupdater
9697c7264d chore: update stage0 2025-07-05 01:13:38 +00:00
Leonardo de Moura
01b0c3e0cc perf: unfold GT.gt and GE.ge in the grind normalizer (#9199) 2025-07-05 00:41:43 +00:00
Cameron Zwarich
37cffbda51 fix: consider Prop-rebundled higher-order params to be fixed (#9198)
This PR changes the compiler's specialization analysis to consider
higher-order params that are rebundled in a way that only changes their
`Prop` arguments to be fixed. This means that they get specialized with
a mere `@[specialize]`, rather than the compiler having to opt-in to
more aggressive parameter-specific specialization.
2025-07-05 00:02:24 +00:00
Leonardo de Moura
f5e47480f2 chore: #9196 part 2 (#9197)
#9196 part 2 after update stage0
2025-07-04 23:27:00 +00:00
Lean stage0 autoupdater
66ffd8d5c2 chore: update stage0 2025-07-04 21:12:35 +00:00
Leonardo de Moura
162e81af57 perf: normalize forall expressions using a simproc in grind (#9196)
This PR implements `forall` normalization using a simproc instead of
rewriting rules in `grind`. This is the first part of the PR, after
update stage0, we must remove the normalization theorems.
2025-07-04 20:41:02 +00:00
Leonardo de Moura
2bf4192ab7 fix: unexpected kernel projection issue in grind (#9193)
This PR fixes the unexpected kernel projection issue reported by issue
#9187

closes #9187
2025-07-04 17:17:40 +00:00
Lean stage0 autoupdater
106d50e46c chore: update stage0 2025-07-04 13:05:44 +00:00
Sebastian Graf
d89f336db2 fix: Scope PostCond.total to Std.Do by making it non-builtin (#9184)
This PR fixes stealing of `⇓` syntax by the new notation for total
postconditions by demoting it to non-builtin syntax and scoping it to
`Std.Do`.

Co-authored-by: Sebastian Graf <sg@lean-fro.org>
2025-07-04 12:33:45 +00:00
Leonardo de Moura
e9a55bfff7 chore: move test to run (#9183) 2025-07-04 00:33:39 +00:00
Leonardo de Moura
55d5ace68e feat: pattern inference using symbol priorities in grind (#9182)
This PR tries to improve the E-matching pattern inference for `grind`.
That said, we still need better tools for annotating and maintaining
`grind` annotations in libraries.

closes #9125
2025-07-03 16:47:38 -07:00
Sebastian Ullrich
357b5f9ed8 chore: CI: restore cache in update-stage0 (#9179)
Avoid rebuilding stage 0 all the time
2025-07-03 20:55:14 +00:00
Cameron Zwarich
b1e5ecc582 chore: add a #guard_msgs to tests/lean/run/instanceUsingFalse.lean (#9180)
This test originally failed by hitting unreachable code, which is caught
by the test harness, but it's probably good to also check the result.
2025-07-03 20:42:12 +00:00
Paul Reichert
cd445dce76 refactor: replace some Subarray functions with generic slice functions (#9017)
This PR removes the `Subarray`-specific `toArray`, `foldlM` and `foldl`
methods and instead provides these operations on `Std.Slice`, which are
implemented with the `ToIterator` instance of the slice. Calling
`subarray.toArray` etc. still works, since `Subarray` is an abbreviation
for `Slice _`.

Because the benchmarks are not so clear, to be safe, I will merge this
only after the release. In contrast to the ranges, the iteration over
slices is not quite as efficient as the old `Subarray`-specific
implementation, which would require either more optimizations in the
iterator library (special `IteratorLoop` and `IteratorCollect`
implementations) or better unboxing support by the compiler.
2025-07-03 19:33:19 +00:00
Cameron Zwarich
501993eb7f fix: don't pull instances depending on erased propositions (#9177)
This PR makes the `pullInstances` pass avoid pulling any instance
expressions containing erased propositions, because we don't correctly
represent the dependencies that remain after erasure.
2025-07-03 19:17:25 +00:00
Mac Malone
9ed51959ef refactor: ignore the setup-file header in the server for now (#9163)
This PR disables the use of the header produced by `lake setup-file` in
the server for now. It will be re-enabled once Lake takes into account
the header given by the server when processing workspace modules.
Without that, `setup-file` header can produce odd behavior when the file
on disk and in an editor disagree on whether the file participates in
the module system.
2025-07-03 17:58:07 +00:00
Eric Wieser
0106ca3bec fix: undefined symbol without LEAN_USE_GMP (#9106)
This PR fixes `undefined symbol: lean::mpz::divexact(lean::mpz const&,
lean::mpz const&)` when building without `LEAN_USE_GMP`

This fixes a regression in #8089
2025-07-03 16:50:21 +00:00
Sebastian Ullrich
ba7135d73c fix: exposed wellfounded recursion (#9173)
This PR fixes an incompatibility in the experimental module system when
trying to combine wellfounded recursion with public exposed definitions.
2025-07-03 16:48:15 +00:00
Joachim Breitner
47b795a302 chore: CI: run stage0 update on faster runner (#9178)
To avoid it losing races against the merge queue.
2025-07-03 16:14:46 +00:00
Lean stage0 autoupdater
0b6df7d6a4 chore: update stage0 2025-07-03 16:14:28 +00:00
Sebastian Graf
c6689584ea fix: split ifs in mvcgen rather than relying on a spec (#9176)
This PR makes `mvcgen` split ifs rather than applying specifications.
Doing so fixes a bug reported by Rish.

Co-authored-by: Sebastian Graf <sg@lean-fro.org>
2025-07-03 14:29:17 +00:00
grunweg
a7c982204e doc: use modern configuration syntax in the Simp.Config documentation (#9174)
The new config syntax is preferred for new code: change the
documentation to use it.

This was [discussed on
zulip](https://leanprover.zulipchat.com/#narrow/channel/113488-general/topic/Using.20config.20vs.20optConfig.20in.20language.20documentation/with/526948836).
2025-07-03 14:16:37 +00:00
François G. Dorais
77d79f705f fix: typos in Std.Classes.Ord.Basic (#9145)
This PR fixes two typos.
2025-07-03 12:04:25 +00:00
Leonardo de Moura
ff130a25a2 fix: bug at matchEqBwdPat (#9172)
This PR fixes a bug at `matchEqBwdPat`. The type may contain pattern
variables.
2025-07-03 07:05:01 +00:00
Kim Morrison
c06af84d9f fix: refactor grind's module/ring design to avoid a diamond (#9168)
This PR resolves a defeq diamond, which caused a problem in Mathlib:
```
import Mathlib

example (R : Type) [I : Ring R] :
  @AddCommGroup.toGrindIntModule R (@Ring.toAddCommGroup R I) =
    @Lean.Grind.Ring.instIntModule R (@Ring.toGrindRing R I) := rfl -- fails
```
2025-07-03 06:50:46 +00:00
Leonardo de Moura
5f818826d1 feat: add [grind symbol <prio>] attribute (#9169)
This PR adds the attribute `[grind symbol <prio>]`. This is just the
first part of the PR.
2025-07-03 06:06:55 +00:00
Cameron Zwarich
c8ab8f45aa chore: share duplicated code for enum scalar representation (#9170) 2025-07-03 05:33:35 +00:00
Mac Malone
6f85e32501 fix: lake: recreate static archives & use T, not --thin (#9165)
This PR fixes two issues with Lake's process of creating static
archives.

Lake now always recreates static archives by first deleting any existing
one and then recreating it. `ar rcs` does not remove delete files, so
running it when the archive already exists can leave behind "ghost"
symbols of removed object files.

Second, Lake now use `T` rather than `--thin` to create thin archives.
While `--thin` is the recommended spelling, older versions of LLVM `ar`
do not support it. Thus, either choice produces tradeoffs. `T` is chosen
to make Lake consistent with the Lean core's own (Make) build scripts.
2025-07-03 03:33:10 +00:00
Cameron Zwarich
174b1301d8 chore: remove VarInfo defaults in IR RC pass (#9167)
These defaults don't make the code easier to understand.
2025-07-03 03:15:07 +00:00
Cameron Zwarich
01d32aa408 chore: add test for #9156 after stage0 update (#9166)
Fixes #9156.
2025-07-03 02:06:21 +00:00
Lean stage0 autoupdater
c832577470 chore: update stage0 2025-07-03 01:40:52 +00:00
Cameron Zwarich
cc7c9b48a0 fix: don't inline computed fields _override implementations in base phase (#9159)
This PR enforces the non-inlining of _override impls in the base phase
of LCNF compilation. The current situation allows for constructor/cases
mismatches to be exposed to the simplifier, which triggers an assertion
failure. The reason this didn't show up sooner for Expr is that Expr has
a custom extern implementation of its computed field getter.

Fixes #9156.
2025-07-03 00:26:01 +00:00
Cameron Zwarich
2b788b1a62 chore: make tests/lean/run/2291.lean less sensitive (#9164)
This test was originally checked in for a panic in the pretty printer,
but at some point the output of every LCNF simp pass was added to
#guard_msgs output. Since this is printing LCNF built by the stage0
compiler, this causes a lot of unnecessary churn.
2025-07-02 23:27:06 +00:00
Mac Malone
2e8102424f refactor: lake: use r for ir key in content hashes (#9162)
This PR changes the key Lake uses for the `,ir` artifact in the content
hash data structure to `r`, maintaining the convention of single
character key names.
2025-07-02 22:59:13 +00:00
Rob23oba
a0bb5f4961 chore: fixes for #9158 after stage0 update (#9161) 2025-07-02 18:46:21 +00:00
Lean stage0 autoupdater
921d252253 chore: update stage0 2025-07-02 18:26:42 +00:00
Rob23oba
3ede96accc fix: use patternIgnore(...) in grind syntax (#9158)
This PR fixes the syntax of `grind` modifiers to use `patternIgnore` for
cases where both unicode and ascii variants are matched. This fixes an
issue where several variants of grind syntax weren't accepted (e.g.
`@[grind ← gen]`). Additionally, this reduces the chance that we get
another syntax matching bootstrap hell.
2025-07-02 17:14:21 +00:00
Rob23oba
7aca460c11 fix: add groups around simpLemma and grindLemma syntax (#9157)
This PR wraps `simpLemma` and `grindLemma` in `ppGroup` to make sure
that the modifiers aren't printed separately from the term / identifier.
Example:
```
simp only [very_long_lemma_oh_no_can_you_please_stop_we're_getting_to_the_limit, ←
  wait_this_is_rewritten_backwards_oh_uhh_where's_the_arrow_you_ask?_oh_wait_it's_up_there!]
==>
simp only [very_long_lemma_oh_no_can_you_please_stop_we're_getting_to_the_limit,
  ← wait_this_is_rewritten_backwards_and_wow_it's_very_clear_and_obvious]
```
2025-07-02 15:11:51 +00:00
Cameron Zwarich
8954354216 fix: tighten IR typing rules for applications of closures (#9154)
This PR tightens the IR typing rules around applications of closures.
When re-reading some code, I realized that the code in `mkPartialApp`
has a clear typo—`.object` and `type` should be swapped. However, it
doesn't matter, because later IR passes smooth out the mismatch here. It
makes more sense to be strict up-front and require applications of
closures to always return an `.object`.
2025-07-02 14:06:24 +00:00
Joachim Breitner
977ae92e43 fix: module system: remove WellFounded-specific hacks (#9143)
This PR removes a rather ugly hack in the module system, exposing the
bodies of theorems whose type mention `WellFounded`.

The original motivation was that reducing well-founded definitions (e.g.
in `by rfl`) requires reducing proofs, so they need to be available.

But reducing proofs is generally fraught with peril, and we have been
nudging our users away from using it for a while, e.g. in #5182. Since
the module system is opt-in and users will gradually migrate to it, it
may be reasonable to expect them to avoid reducing well-founded
recursion in the process

This way we don't need hacks like this (which, without evidence, I
believe would be incomplete anyways) and we get the nice guarantee that
within the module system, theorems bodies are always private.
2025-07-02 11:58:50 +00:00
Sebastian Ullrich
2f162005b8 refactor: module-ize Std.Data.DHashMap (#9098) 2025-07-02 10:00:17 +00:00
Paul Reichert
84cd2c49eb feat: remove unnecessary decidability requirements (#9096)
This PR removes some unnecessary `Decidable*` instance arguments by
using lemmas in the `Classical` namespace instead of the `Decidable`
namespace.

This might lead to some additional dependency on classical axioms, but
large parts of the standard library are relying on them either way.
2025-07-02 06:20:50 +00:00
Paul Reichert
561f347f5a feat: universe-polymorphic loop operations on pure iterators (#9135)
This PR allows the result type of `forIn`, `foldM` and `fold` on pure
iterators (`Iter`) to be in a different universe than the iterators.
2025-07-02 06:18:20 +00:00
Leonardo de Moura
a4a3a3b596 feat: improve linarith markVars (#9153)
This PR improves the linarith `markVars`, and ensures it does not
produce spurious issue messages.
2025-07-02 05:05:10 +00:00
David Thrane Christiansen
8c0cff83bd doc: update obsolete docstring for registerDerivingHandler (#9152)
This PR fixes an obsolete docstring for `registerDerivingHandler`
2025-07-02 04:03:00 +00:00
Leonardo de Moura
094dd588d6 chore: simproc and helper theorems for grind (#9151) 2025-07-02 03:57:12 +00:00
Rob23oba
e6954b7837 fix: revert state on compilation failure (new compiler) (#8691)
This PR ensures that the state is reverted when compilation using the
new compiler fails. This is especially important for noncomputable
sections where the compiler might generate half-compiled functions which
may then be erroneously used while compiling other functions.
2025-07-02 03:42:00 +00:00
Leonardo de Moura
4a539715c8 fix: missing case at CommRing.toPoly (#9150)
This PR adds a missing case in the `toPoly` function used in `grind`.
2025-07-02 02:53:48 +00:00
Leonardo de Moura
2b1b2ed45c feat: pow_add for any semirings in grind (#9149)
This PR generalizes the `a^(m+n)` grind normalizer to any semirings.
Example:
```
variable [Field R]

example (M : R) (h₀ : M ≠ 0) {n : Nat} (hn : n > 0) : M ^ n / M = M ^ (n - 1) := by
  cases n <;> grind
```
2025-07-02 01:43:35 +00:00
Leonardo de Moura
b67fb4fa66 feat: polynomial operations with deep recursion and heartbeat checks (#9146)
This PR adds "safe" polynomial operations to `grind ring`. The use the
usual combinators: `withIncRecDepth` and `checkSystem`.
2025-07-02 00:05:28 +00:00
Cameron Zwarich
2864efb222 feat: support enums modulo irrelevance (#9144)
This PR adds support for representing more inductive as enums,
summarized up as extending support to those that fail to be enums
because of parameters or irrelevant fields. While this is nice to have,
it is actually motivated by correctness of a future desired
optimization. The existing type representation is unsound if we
implement `object`/`tobject` distinction between values guaranteed to be
an object pointer and those that may also be a tagged scalar. In
particular, types like the ones added in this PR's tests would have all
of their constructors encoded via tagged values, but under the natural
extension of the existing rules of type representation they would be
considered `object` rather than `tobject`.
2025-07-01 22:35:50 +00:00
Cameron Zwarich
f91d6ce16f chore: cache IR types of named types (#9140)
This PR converts the `lowerEnumToScalarType?` cache to a cache of IR
types of named types. This is more sensible than just focusing on the
enum optimization, and due to uniform representation of polymorphism we
have to compile `Constant T1` and `Constant T2` to the same
representation.
2025-07-01 21:39:05 +00:00
dependabot[bot]
8e5dfb0fd1 chore: CI: bump softprops/action-gh-release from 2.2.2 to 2.3.2 (#9139)
Bumps
[softprops/action-gh-release](https://github.com/softprops/action-gh-release)
from 2.2.2 to 2.3.2.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/softprops/action-gh-release/releases">softprops/action-gh-release's
releases</a>.</em></p>
<blockquote>
<h2>v2.3.2</h2>
<ul>
<li>fix: revert fs <code>readableWebStream</code> change</li>
</ul>
<h2>v2.3.1</h2>
<!-- raw HTML omitted -->
<h2>What's Changed</h2>
<h3>Bug fixes 🐛</h3>
<ul>
<li>fix: fix file closing issue by <a
href="https://github.com/WailGree"><code>@​WailGree</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/629">softprops/action-gh-release#629</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/WailGree"><code>@​WailGree</code></a>
made their first contribution in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/629">softprops/action-gh-release#629</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/softprops/action-gh-release/compare/v2.3.0...v2.3.1">https://github.com/softprops/action-gh-release/compare/v2.3.0...v2.3.1</a></p>
<h2>v2.3.0</h2>
<!-- raw HTML omitted -->
<ul>
<li>Migrate from jest to vitest</li>
<li>Replace <code>mime</code> with <code>mime-types</code></li>
<li>Bump to use node 24</li>
<li>Dependency updates</li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/softprops/action-gh-release/compare/v2.2.2...v2.3.0">https://github.com/softprops/action-gh-release/compare/v2.2.2...v2.3.0</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md">softprops/action-gh-release's
changelog</a>.</em></p>
<blockquote>
<h2>2.3.2</h2>
<ul>
<li>fix: revert fs <code>readableWebStream</code> change</li>
</ul>
<h2>2.3.1</h2>
<h3>Bug fixes 🐛</h3>
<ul>
<li>fix: fix file closing issue by <a
href="https://github.com/WailGree"><code>@​WailGree</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/629">softprops/action-gh-release#629</a></li>
</ul>
<h2>2.3.0</h2>
<ul>
<li>Migrate from jest to vitest</li>
<li>Replace <code>mime</code> with <code>mime-types</code></li>
<li>Bump to use node 24</li>
<li>Dependency updates</li>
</ul>
<h2>2.2.2</h2>
<h2>What's Changed</h2>
<h3>Bug fixes 🐛</h3>
<ul>
<li>fix: updating release draft status from true to false by <a
href="https://github.com/galargh"><code>@​galargh</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/316">softprops/action-gh-release#316</a></li>
</ul>
<h3>Other Changes 🔄</h3>
<ul>
<li>chore: simplify ref_type test by <a
href="https://github.com/steinybot"><code>@​steinybot</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/598">softprops/action-gh-release#598</a></li>
<li>fix(docs): clarify the default for tag_name by <a
href="https://github.com/muzimuzhi"><code>@​muzimuzhi</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/599">softprops/action-gh-release#599</a></li>
<li>test(release): add unit tests when searching for a release by <a
href="https://github.com/rwaskiewicz"><code>@​rwaskiewicz</code></a> in
<a
href="https://redirect.github.com/softprops/action-gh-release/pull/603">softprops/action-gh-release#603</a></li>
<li>dependency updates</li>
</ul>
<h2>2.2.1</h2>
<h2>What's Changed</h2>
<h3>Bug fixes 🐛</h3>
<ul>
<li>fix: big file uploads by <a
href="https://github.com/xen0n"><code>@​xen0n</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/562">softprops/action-gh-release#562</a></li>
</ul>
<h3>Other Changes 🔄</h3>
<ul>
<li>chore(deps): bump <code>@​types/node</code> from 22.10.1 to 22.10.2
by <a href="https://github.com/dependabot"><code>@​dependabot</code></a>
in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/559">softprops/action-gh-release#559</a></li>
<li>chore(deps): bump <code>@​types/node</code> from 22.10.2 to 22.10.5
by <a href="https://github.com/dependabot"><code>@​dependabot</code></a>
in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/569">softprops/action-gh-release#569</a></li>
<li>chore: update error and warning messages for not matching files in
files field by <a
href="https://github.com/ytimocin"><code>@​ytimocin</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/568">softprops/action-gh-release#568</a></li>
</ul>
<h2>2.2.0</h2>
<h2>What's Changed</h2>
<h3>Exciting New Features 🎉</h3>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="72f2c25fcb"><code>72f2c25</code></a>
release 2.3.2</li>
<li><a
href="552dc5524b"><code>552dc55</code></a>
fix: revert <code>fs:readableWebStream</code> change (<a
href="https://redirect.github.com/softprops/action-gh-release/issues/632">#632</a>)</li>
<li><a
href="f3cad8bcbf"><code>f3cad8b</code></a>
release 2.3.1</li>
<li><a
href="07a2257003"><code>07a2257</code></a>
fix: fix file closing issue (<a
href="https://redirect.github.com/softprops/action-gh-release/issues/629">#629</a>)</li>
<li><a
href="d5382d3e6f"><code>d5382d3</code></a>
release 2.3.0</li>
<li><a
href="a0e2122208"><code>a0e2122</code></a>
feat: migrate from jest to vitest (<a
href="https://redirect.github.com/softprops/action-gh-release/issues/626">#626</a>)</li>
<li><a
href="8836085300"><code>8836085</code></a>
chore: replace <code>mime</code> with <code>mime-types</code> (<a
href="https://redirect.github.com/softprops/action-gh-release/issues/624">#624</a>)</li>
<li><a
href="86463358d8"><code>8646335</code></a>
chore: bump node to 20.19.2</li>
<li><a
href="46b284799f"><code>46b2847</code></a>
chore(deps): bump the npm group across 1 directory with 5 updates (<a
href="https://redirect.github.com/softprops/action-gh-release/issues/623">#623</a>)</li>
<li><a
href="37fd9d0351"><code>37fd9d0</code></a>
chore(deps): bump undici from 5.28.5 to 5.29.0 (<a
href="https://redirect.github.com/softprops/action-gh-release/issues/621">#621</a>)</li>
<li>Additional commits viewable in <a
href="da05d55257...72f2c25fcb">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=softprops/action-gh-release&package-manager=github_actions&previous-version=2.2.2&new-version=2.3.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-01 21:22:15 +00:00
dependabot[bot]
5c86fd271f chore: CI: bump dawidd6/action-download-artifact from 10 to 11 (#9137)
Bumps
[dawidd6/action-download-artifact](https://github.com/dawidd6/action-download-artifact)
from 10 to 11.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/dawidd6/action-download-artifact/releases">dawidd6/action-download-artifact's
releases</a>.</em></p>
<blockquote>
<h2>v11</h2>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/dawidd6/action-download-artifact/compare/v10...v11">https://github.com/dawidd6/action-download-artifact/compare/v10...v11</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="ac66b43f0e"><code>ac66b43</code></a>
node_modules: upgrade</li>
<li><a
href="9b54a0a70c"><code>9b54a0a</code></a>
Update README.md</li>
<li>See full diff in <a
href="https://github.com/dawidd6/action-download-artifact/compare/v10...v11">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dawidd6/action-download-artifact&package-manager=github_actions&previous-version=10&new-version=11)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-01 21:21:43 +00:00
dependabot[bot]
402cba6f09 chore: CI: bump dcarbone/install-jq-action from 3.1.1 to 3.2.0 (#9138)
Bumps
[dcarbone/install-jq-action](https://github.com/dcarbone/install-jq-action)
from 3.1.1 to 3.2.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/dcarbone/install-jq-action/releases">dcarbone/install-jq-action's
releases</a>.</em></p>
<blockquote>
<h2>v3.2.0</h2>
<h2>What's Changed</h2>
<ul>
<li>case sensitive is off by <a
href="https://github.com/Rupreht"><code>@​Rupreht</code></a> in <a
href="https://redirect.github.com/dcarbone/install-jq-action/pull/19">dcarbone/install-jq-action#19</a></li>
<li>Adding 1.8.0 stuff by <a
href="https://github.com/dcarbone"><code>@​dcarbone</code></a> in <a
href="https://redirect.github.com/dcarbone/install-jq-action/pull/20">dcarbone/install-jq-action#20</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/Rupreht"><code>@​Rupreht</code></a> made
their first contribution in <a
href="https://redirect.github.com/dcarbone/install-jq-action/pull/19">dcarbone/install-jq-action#19</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/dcarbone/install-jq-action/compare/v3.1.1...v3.2.0">https://github.com/dcarbone/install-jq-action/compare/v3.1.1...v3.2.0</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="b7ef57d46e"><code>b7ef57d</code></a>
Adding 1.8.0 stuff (<a
href="https://redirect.github.com/dcarbone/install-jq-action/issues/20">#20</a>)</li>
<li><a
href="2eac2baa38"><code>2eac2ba</code></a>
case sensitive is off (<a
href="https://redirect.github.com/dcarbone/install-jq-action/issues/19">#19</a>)</li>
<li>See full diff in <a
href="https://github.com/dcarbone/install-jq-action/compare/v3.1.1...v3.2.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dcarbone/install-jq-action&package-manager=github_actions&previous-version=3.1.1&new-version=3.2.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-01 21:21:20 +00:00
Cameron Zwarich
c0aad8a27c chore: remove unnecessary special case for Bool (#9136) 2025-07-01 20:42:58 +00:00
Cameron Zwarich
dbcf5b9d9d fix: call lowerEnumToScalarType? with ConstructorVal.induct (#9134)
This PR changes ToIR to call `lowerEnumToScalarType?` with
`ConstructorVal.induct` rather than the name of the constructor itself.
This was an oversight in some refactoring of code in the new compiler
before landing it. It should not affect runtime of compiled code (due to
the extra tagging/untagging being optimized by LLVM), but it does make
IR for the interpreter slightly more efficient.
2025-07-01 20:00:34 +00:00
jrr6
d31dfe92de fix: account for namespaces/open decls in inlineExpr (#9108)
This PR fixes an issue that may have caused inline expressions in
messages to be unnecessarily rendered on a separate line.
2025-07-01 19:28:22 +00:00
Kyle Miller
a018ed3f0f feat: add usedLetOnly to LocalContext binder functions (#9131)
This PR adds a `usedLetOnly` parameter to `LocalContext.mkLambda` and
`LocalContext.mkForall`, to parallel the `MetavarContext` versions.
2025-07-01 18:41:49 +00:00
Leonardo de Moura
535ce0b8fd feat: pow_add normalization in grind (#9133)
This PR adds support for `a^(m+n)` in the `grind` normalizer.
2025-07-01 17:52:16 +00:00
Leonardo de Moura
2bfcb1f25c fix: expand pattern offset gadget in constant patterns (#9130)
This PR fixes unexpected occurrences of the `Grind.offset` gadget in
ground patterns. See new test
2025-07-01 16:31:58 +00:00
Rob23oba
0e5ce1496b fix: pretty-printing of grind syntax (#9128)
This PR fixes spacing in the `grind` attribute and tactic syntax.
Previously `@[grind]` was incorrectly pretty-printed as `@[grind ]`, and
`grind [...] on_failure ...` was pretty-printed `grind [...]on_failure
...`. Fixes that `on_failure` was reserved as keyword.
2025-07-01 16:15:11 +00:00
Eric Wieser
688d9a30d2 fix: incorrectly parenthesized Bool.nots (#9129)
This PR fixes simp lemmas about boolean equalities to say `(!x) = y`
instead of `(!decide (x = y)) = true`

This might be an argument for changing the operator precedence of `!`,
or writing a linter to detect these mistakes.

Zulip thread: [#lean4 > Sum.bnot_isLeft and Sum.bnot_isRight @
💬](https://leanprover.zulipchat.com/#narrow/channel/270676-lean4/topic/Sum.2Ebnot_isLeft.20and.20Sum.2Ebnot_isRight/near/525938158)
2025-07-01 15:57:14 +00:00
Parth Shastri
2c13d145dc fix: match against app fn for reducing recursor in whnfCore (#9090)
This PR fixes a bug in `whnfCore` where it would fail to reduce
applications of recursors/auxiliary defs.

Closes #9089
2025-07-01 13:30:31 +00:00
Eric Wieser
232443371b perf: add missing std::moves (#9107)
Continues from #4700.

This will save a handful of refcounts here and there.
2025-07-01 12:39:12 +00:00
Paul Reichert
c231b742ca refactor: move well-founded relations used by the iterators to init (#9095)
This PR moves the construction of the `Option.SomeLtNone.lt` (and `le`)
relation, in which `some` is less than `none`, to
`Init.Data.Option.Basic` and moves well-foundedness proofs for
`Option.lt` and `Option.SomeLtNone.lt` into `Init.Data.Option.Lemmas`.
2025-07-01 12:02:48 +00:00
Paul Reichert
c9dea51f7a chore: create iterator benchmark (#9094)
This PR adds a benchmark file that exemplifies some iterator usages
2025-07-01 11:47:36 +00:00
Eric Wieser
72f421054d fix: do not truncate at null bytes in panic messages (#9103)
This PR prevents truncation of `panic!` messages containing null bytes.

The C api for `lean_panic` is left untouched.

Closes #9102
2025-07-01 11:34:16 +00:00
Joachim Breitner
8424ddbb3e feat: prettier expected type mismatch error message (#9099)
This PR improves the “expected type mismatch” error message by omitting
the type's types when they are defeq, and putting them into separate
lines when not.

I found it rather tediuos to parse the error message when the expected
type is long, because I had to find the `:` in the middle of a large
expression somewhere. Also, when both are of sort `Prop` or `Type` it
doesn't add much value to print the sort (and it’s only one hover away
anyways).
2025-07-01 07:50:53 +00:00
Kim Morrison
6ab8ed34d0 chore: grind test case for matching Nat arguments (#9123) 2025-07-01 07:21:36 +00:00
Kim Morrison
0af3659d14 feat: attribute [grind cases eager] PProd MProd (#9121)
This PR allows `grind` to case on the universe variants of `Prod`.
2025-07-01 04:02:47 +00:00
Kim Morrison
8c1e5c5c07 chore: allow grind to unfold Array ifInBounds operations (#9120) 2025-07-01 02:44:27 +00:00
Kim Morrison
293d1dfd57 chore: improvements to release automation (#9119) 2025-07-01 02:39:10 +00:00
Cameron Zwarich
604312a3df chore: update doc/dev/ffi.md after #9088 (#9112) 2025-07-01 01:00:59 +00:00
Kim Morrison
835bc675ca chore: begin development cycle for v4.23.0 (#9118) 2025-07-01 00:40:35 +00:00
Cameron Zwarich
463f2c5f25 chore: improve readability of a zipWith call (#9116) 2025-07-01 00:10:54 +00:00
Cameron Zwarich
52ab0141cd chore: share more code in toIRType (#9115) 2025-06-30 23:13:02 +00:00
Kim Morrison
cd60e3b8fd feat: further release automation (#9114)
This PR further improves release automation, automatically incorporating
material from `nightly-testing` and `bump/v4.X.0` branches in the bump
PRs to downstream repositories.
2025-06-30 22:28:00 +00:00
Leonardo de Moura
b9e440d280 doc: improve grind doc string (#9113)
This PR improves the `grind` doc string and tries to make it more
approachable to new user.
2025-06-30 21:47:40 +00:00
Lean stage0 autoupdater
5296fa1dd5 chore: update stage0 2025-06-30 21:08:11 +00:00
Sebastian Ullrich
3d74e1ba44 chore: track .ir output files in Lake (#9060)
Co-authored-by: Mac Malone <tydeu@hatpress.net>
2025-06-30 15:59:18 +00:00
Sebastian Ullrich
de2d6ba37e perf: do not import non-template IR for codegen (#8666)
This PR adjusts the experimental module system to not import the IR of
non-`meta` declarations. It does this by replacing such IR with opaque
foreign declarations on export and adjusting the new compiler
accordingly.

This PR should not be merged before the new compiler.

Based on #8664.
2025-06-30 15:52:56 +00:00
Mac Malone
9db41f9931 fix: lake: source file not in module input trace & some logs dropped (#9101)
This PR fixes a bug introduce by #9081 where the source file was dropped
from the module input trace and some entries were dropped from the
module job log.
2025-06-30 15:48:01 +00:00
Cameron Zwarich
30fee8fb67 chore: update stage0 2025-06-30 15:39:58 +02:00
Cameron Zwarich
4c7ab7fc79 chore: set prefer_native=true for bootstrap 2025-06-30 15:39:58 +02:00
Cameron Zwarich
6f854a97a4 chore: update stage0 2025-06-30 15:39:58 +02:00
Cameron Zwarich
2e627d3692 feat: move constructor layout to Lean and add a few optimizations
This PR moves the constructor layout code from C++ to Lean. When
writing the new compiler, we just reused the existing C++ code,
even though it was a bit inconvenient, because we wanted to
ensure that constructor layout always matched the existing
compiler.

This fixes #2589 by handling struct field types just like any
other type being lowered, and thus applying the trivial structure
optimization in the process. Originally, I wanted to port the
code to Lean without any functional changes, but I found that
it took less code to just implement it "correctly" and get this
fix as a consequence than to emulate the bugs of the existing
C++ implementation.
2025-06-30 15:39:58 +02:00
Sebastian Graf
81fd7edd19 fix: More consistent transparency when calling mspec from mvcgen (#9097)
This PR ensures that `mspec` uses the configured transparency setting
and makes `mvcgen` use default transparency when calling `mspec`.

Co-authored-by: Sebastian Graf <sg@lean-fro.org>
2025-06-30 09:57:57 +00:00
Sebastian Ullrich
dfbebe0683 refactor: module-ize Std.Classes (#9079) 2025-06-30 09:45:24 +00:00
David Thrane Christiansen
9bbd2e64aa doc: add missing docstring for ToFormat.toFormat (#9093)
This PR adds a missing docstring for `ToFormat.toFormat`.
2025-06-30 06:59:12 +00:00
Kim Morrison
ae89b7ed43 feat: further release automation (#9092)
This PR further updates release automation. The per-repository update
scripts `script/release_steps.py` now actually performs the tests,
rather than outputting a script for the release manager to run line by
line. It's been tested on `v4.21.0` (i.e. the easy case of a stable
release), and we'll debug its behaviour on `v4.22.0-rc1` tonight.
2025-06-30 05:44:10 +00:00
David Thrane Christiansen
ede8a7e494 fix: error explanation needs updating (#9091)
This PR updates an error explanation to match the actual error.
2025-06-30 05:10:04 +00:00
Kyle Miller
044bfdb098 feat: eliminate letFun support, deprecate let_fun syntax (#9086)
This PR deprecates `let_fun` syntax in favor of `have` and removes
`letFun` support from WHNF and `simp`.
2025-06-30 02:10:18 +00:00
Mac Malone
5049a4893e refactor: lake: fix local artifact cache bugs, opt-in, & related cleanup (#9068)
This PR fixes some bugs with the local Lake artifact cache and cleans up
the surrounding API. It also adds the ability to opt-in to the cache on
packages without `enableArtifactCache` set using the
`LAKE_ARTIFACT_CACHE` environment variable.

Bug-wise, this fixes an issue where cached executable did not have right
permissions to run on Unix systems and a bug where cached artifacts
would not be invalidated on changes. Lake also now writes a trace file
to local build directory if there is none when fetching an artifact from
the cache. This trace has a new `synthetic` field set to `true` to
distinguish it from traces produced by full builds.
2025-06-30 01:02:55 +00:00
Lean stage0 autoupdater
d6c5c8c880 chore: update stage0 2025-06-30 01:20:30 +00:00
Kyle Miller
32894e7349 feat: remove irreducible from letFun (#9087)
This PR removes the `irreducible` attribute from `letFun`, which is one
step toward removing special `letFun` support; part of #9086.

Removing the attribute seems to break some `module` tests in stage2.
2025-06-30 00:04:59 +00:00
Sebastian Ullrich
d53d4722cc chore: compile stage 0 against correct version string (#9085)
This ensure the correct version string is embedded into shipped .oleans,
though only the githash is relevant for the version check.
2025-06-29 20:52:46 +00:00
Kyle Miller
cb3174b1c6 feat: hovers when pp.oneline is true (#7954)
This PR improves `pp.oneline`, where it now preserves tags when
truncating formatted syntax to a single line. Note that the `[...]`
continuation does not yet have any functionality to enable seeing the
untruncated syntax. Closes #3681.
2025-06-29 20:06:24 +00:00
Kyle Miller
68c006a95b feat: transform nondependent lets into haves in declarations and equation lemmas (#8373)
This PR enables transforming nondependent `let`s into `have`s in a
number of contexts: the bodies of nonrecursive definitions, equation
lemmas, smart unfolding definitions, and types of theorems. A motivation
for this change is that when zeta reduction is disabled, `simp` can only
effectively rewrite `have` expressions (e.g. `split` uses `simp` with
zeta reduction disabled), and so we cache the nondependence calculations
by transforming `let`s to `have`s. The transformation can be disabled
using `set_option cleanup.letToHave false`.

Uses `Meta.letToHave`, introduced in #8954.
2025-06-29 19:45:45 +00:00
Kyle Miller
44c8b0df85 feat: warn.sorry option (#8662)
This PR adds a `warn.sorry` option (default true) that logs the
"declaration uses 'sorry'" warning when declarations contain `sorryAx`.
When false, the warning is not logged.

Closes #8611 (assuming that one would set `warn.sorry` as an extra flag
when building).

Other change: Uses `warn.sorry` when creating auxiliary declarations in
`structure` elaborator, to suppress irrelevant 'sorry' warnings.

We could include the sorries themselves in the message if they are
labeled, letting users "go to definition" to see where the sorries are
coming from.

In an earlier version, added additional information to the warning when
it is a synthetic sorry, since these can be caused by elaboration bugs
and they can also be caused by elaboration failures in previous
declarations. This idea needs some more work, so it's not included.
2025-06-29 19:31:17 +00:00
Cameron Zwarich
85c45c409e chore: move lowerType to ToIRType and rename it (#9083) 2025-06-29 19:16:00 +00:00
Mac Malone
e0354cd856 fix: lake: module builds not appearing in job monitor (#9081)
This PR fixes a bug with Lake where the job monitor would sit on a
top-level build (e.g., `mathlib/Mathlib:default`) instead of reporting
module build progress.

The issue was actually simpler than it initially appeared. The wrong
portion of the module build was being registered to job monitor. Moving
it to right place fixes it, no job priorities necessary.
2025-06-29 18:39:06 +00:00
Cameron Zwarich
5d8cd35471 chore: rename Lean.Compiler.IR.CtorLayout to ToIRType (#9082) 2025-06-29 18:36:55 +00:00
Cameron Zwarich
0b738e07b4 chore: move more functions to CtorLayout (#9080) 2025-06-29 17:31:41 +00:00
Sebastian Ullrich
f475d5a428 chore: module-ize Init.lean 2025-06-29 16:52:13 +02:00
Sebastian Ullrich
5aa1950c3f chore: update stage0 2025-06-29 16:15:49 +02:00
Sebastian Ullrich
8085d3c930 chore: allow use of the module system in all of core (#9078) 2025-06-29 13:49:27 +00:00
Kim Morrison
a35425b192 feat: support for ReflCmp in grind (#9073)
This PR copies #9069 to handle `ReflCmp` the same way; we need to call
this in propagateUp rather than propagateDown.
2025-06-29 11:36:39 +00:00
Leonardo de Moura
8b1d2fc2d5 feat: OfSemiring.toQ unexpander (#9076)
This PR adds an unexpander for `OfSemiring.toQ`. This an auxiliary
function used by the `ring` module in `grind`, but we want to reduce the
clutter in the diagnostic information produced by `grind`. Example:
```
example [CommSemiring α] [AddRightCancel α] [IsCharP α 0] (x y : α)
    : x^2*y = 1 → x*y^2 = y → x + y = 2 → False := by
  grind
```
produces
```
  [ring] Ring `Ring.OfSemiring.Q α` ▼
    [basis] Basis ▼
      [_] ↑x + ↑y + -2 = 0
      [_] ↑y + -1 = 0
```
2025-06-29 11:22:24 +00:00
Kim Morrison
98e868e3d2 feat: BEq instances for ByteArray/FloatArray (#9075)
This PR adds `BEq` instances for `ByteArray` and `FloatArray` (also a
`DecidableEq` instance for `ByteArray`).
2025-06-29 11:12:48 +00:00
Leonardo de Moura
b95b0069e7 feat: use comm ring module to normalize nonlinear polynomials in grind cutsat (#9074)
This PR uses the commutative ring module to normalize nonlinear
polynomials in `grind cutsat`. Examples:
```lean
example (a b : Nat) (h₁ : a + 1 ≠ a * b * a) (h₂ : a * a * b ≤ a + 1) : b * a^2 < a + 1 := by 
  grind

example (a b c : Int) (h₁ : a + 1 + c = b * a) (h₂ : c + 2*b*a = 0) : 6 * a * b - 2 * a ≤ 2 := by 
  grind
```
2025-06-29 11:09:29 +00:00
2992 changed files with 25638 additions and 21704 deletions

5
.github/actionlint.yaml vendored Normal file
View File

@@ -0,0 +1,5 @@
self-hosted-runner:
labels:
- nscloud-ubuntu-22.04-amd64-4x16
- nscloud-ubuntu-22.04-amd64-8x16
- nscloud-macos-sonoma-arm64-6x14

View File

@@ -97,14 +97,14 @@ jobs:
sudo apt-get update
sudo apt-get install -y gcc-multilib g++-multilib ccache libuv1-dev:i386 pkgconf:i386
if: matrix.cmultilib
- name: Cache
- name: Restore Cache
id: restore-cache
uses: actions/cache/restore@v4
with:
# NOTE: must be in sync with `save` below
# 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

View File

@@ -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}",
@@ -363,7 +370,7 @@ jobs:
with:
path: artifacts
- name: Release
uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631
uses: softprops/action-gh-release@72f2c25fcb47643c292f7107632f7a47c1df5cd8
with:
files: artifacts/*/*
fail_on_unmatched_files: true
@@ -407,7 +414,7 @@ jobs:
echo -e "\n*Full commit log*\n" >> diff.md
git log --oneline "$last_tag"..HEAD | sed 's/^/* /' >> diff.md
- name: Release Nightly
uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631
uses: softprops/action-gh-release@72f2c25fcb47643c292f7107632f7a47c1df5cd8
with:
body_path: diff.md
prerelease: true

View File

@@ -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

View File

@@ -34,7 +34,7 @@ jobs:
- name: Download artifact from the previous workflow.
if: ${{ steps.workflow-info.outputs.pullRequestNumber != '' }}
id: download-artifact
uses: dawidd6/action-download-artifact@v10 # https://github.com/marketplace/actions/download-workflow-artifact
uses: dawidd6/action-download-artifact@v11 # https://github.com/marketplace/actions/download-workflow-artifact
with:
run_id: ${{ github.event.workflow_run.id }}
path: artifacts
@@ -71,7 +71,7 @@ jobs:
GH_TOKEN: ${{ secrets.PR_RELEASES_TOKEN }}
- name: Release (short format)
if: ${{ steps.workflow-info.outputs.pullRequestNumber != '' }}
uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631
uses: softprops/action-gh-release@72f2c25fcb47643c292f7107632f7a47c1df5cd8
with:
name: Release for PR ${{ steps.workflow-info.outputs.pullRequestNumber }}
# There are coredumps files here as well, but all in deeper subdirectories.
@@ -86,7 +86,7 @@ jobs:
- name: Release (SHA-suffixed format)
if: ${{ steps.workflow-info.outputs.pullRequestNumber != '' }}
uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631
uses: softprops/action-gh-release@72f2c25fcb47643c292f7107632f7a47c1df5cd8
with:
name: Release for PR ${{ steps.workflow-info.outputs.pullRequestNumber }} (${{ steps.workflow-info.outputs.sourceHeadSha }})
# There are coredumps files here as well, but all in deeper subdirectories.
@@ -151,7 +151,7 @@ jobs:
- name: 'Setup jq'
if: ${{ steps.workflow-info.outputs.pullRequestNumber != '' }}
uses: dcarbone/install-jq-action@v3.1.1
uses: dcarbone/install-jq-action@v3.2.0
# Check that the most recently nightly coincides with 'git merge-base HEAD master'
- name: Check merge-base and nightly-testing-YYYY-MM-DD for Mathlib/Batteries

View File

@@ -18,7 +18,7 @@ concurrency:
jobs:
update-stage0:
runs-on: ubuntu-latest
runs-on: nscloud-ubuntu-22.04-amd64-8x16
steps:
# This action should push to an otherwise protected branch, so it
# uses a deploy key with write permissions, as suggested at
@@ -52,6 +52,18 @@ jobs:
run: |
echo "NPROC=$(nproc 2>/dev/null || sysctl -n hw.logicalcpu 2>/dev/null || echo 4)" >> $GITHUB_ENV
shell: 'nix develop -c bash -euxo pipefail {0}'
- name: Restore Cache
if: env.should_update_stage0 == 'yes'
uses: actions/cache/restore@v4
with:
# NOTE: must be in sync with `restore-cache` in `build-template.yml`
# TODO: actually switch to USE_LAKE once it caches more; for now it just caches more often than any other build type so let's use its cache
path: |
.ccache
key: Linux Lake-build-v3-${{ github.sha }}
# fall back to (latest) previous cache
restore-keys: |
Linux Lake-build-v3
- if: env.should_update_stage0 == 'yes'
run: cmake --preset release
shell: 'nix develop -c bash -euxo pipefail {0}'

1
.gitignore vendored
View File

@@ -31,3 +31,4 @@ fwOut.txt
wdErr.txt
wdIn.txt
wdOut.txt
downstream_releases/

View File

@@ -16,7 +16,7 @@ foreach(var ${vars})
list(APPEND STAGE1_ARGS "-D${CMAKE_MATCH_1}=${${var}}")
elseif("${currentHelpString}" MATCHES "No help, variable specified on the command line." OR "${currentHelpString}" STREQUAL "")
list(APPEND CL_ARGS "-D${var}=${${var}}")
if("${var}" MATCHES "USE_GMP|CHECK_OLEAN_VERSION")
if("${var}" MATCHES "USE_GMP|CHECK_OLEAN_VERSION|LEAN_VERSION_.*|LEAN_SPECIAL_VERSION_DESC")
# must forward options that generate incompatible .olean format
list(APPEND STAGE0_ARGS "-D${var}=${${var}}")
elseif("${var}" MATCHES "LLVM*|PKG_CONFIG|USE_LAKE|USE_MIMALLOC")

View File

@@ -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

View File

@@ -68,7 +68,7 @@ The memory order of the fields is derived from the types and order of the fields
* Fields of type `USize`
* Other scalar fields, in decreasing order by size
Within each group the fields are ordered in declaration order. **Warning**: Trivial wrapper types still count toward a field being treated as non-scalar for this purpose.
Within each group the fields are ordered in declaration order. Trivial wrapper types count as their underlying wrapped type for this purpose.
* To access fields of the first kind, use `lean_ctor_get(val, i)` to get the `i`th non-scalar field.
* To access `USize` fields, use `lean_ctor_get_usize(val, n+i)` to get the `i`th usize field and `n` is the total number of fields of the first kind.
@@ -80,32 +80,32 @@ structure S where
ptr_1 : Array Nat
usize_1 : USize
sc64_1 : UInt64
ptr_2 : { x : UInt64 // x > 0 } -- wrappers don't count as scalars
sc64_2 : Float -- `Float` is 64 bit
sc64_2 : { x : UInt64 // x > 0 } -- wrappers of scalars count as scalars
sc64_3 : Float -- `Float` is 64 bit
sc8_1 : Bool
sc16_1 : UInt16
sc8_2 : UInt8
sc64_3 : UInt64
sc64_4 : UInt64
usize_2 : USize
ptr_3 : Char -- trivial wrapper around `UInt32`
sc32_1 : UInt32
sc32_1 : Char -- trivial wrapper around `UInt32`
sc32_2 : UInt32
sc16_2 : UInt16
```
would get re-sorted into the following memory order:
* `S.ptr_1` - `lean_ctor_get(val, 0)`
* `S.ptr_2` - `lean_ctor_get(val, 1)`
* `S.ptr_3` - `lean_ctor_get(val, 2)`
* `S.usize_1` - `lean_ctor_get_usize(val, 3)`
* `S.usize_2` - `lean_ctor_get_usize(val, 4)`
* `S.sc64_1` - `lean_ctor_get_uint64(val, sizeof(void*)*5)`
* `S.sc64_2` - `lean_ctor_get_float(val, sizeof(void*)*5 + 8)`
* `S.sc64_3` - `lean_ctor_get_uint64(val, sizeof(void*)*5 + 16)`
* `S.sc32_1` - `lean_ctor_get_uint32(val, sizeof(void*)*5 + 24)`
* `S.sc16_1` - `lean_ctor_get_uint16(val, sizeof(void*)*5 + 28)`
* `S.sc16_2` - `lean_ctor_get_uint16(val, sizeof(void*)*5 + 30)`
* `S.sc8_1` - `lean_ctor_get_uint8(val, sizeof(void*)*5 + 32)`
* `S.sc8_2` - `lean_ctor_get_uint8(val, sizeof(void*)*5 + 33)`
* `S.usize_1` - `lean_ctor_get_usize(val, 1)`
* `S.usize_2` - `lean_ctor_get_usize(val, 2)`
* `S.sc64_1` - `lean_ctor_get_uint64(val, sizeof(void*)*3)`
* `S.sc64_2` - `lean_ctor_get_uint64(val, sizeof(void*)*3 + 8)`
* `S.sc64_3` - `lean_ctor_get_float(val, sizeof(void*)*3 + 16)`
* `S.sc64_4` - `lean_ctor_get_uint64(val, sizeof(void*)*3 + 24)`
* `S.sc32_1` - `lean_ctor_get_uint32(val, sizeof(void*)*3 + 32)`
* `S.sc32_2` - `lean_ctor_get_uint32(val, sizeof(void*)*3 + 36)`
* `S.sc16_1` - `lean_ctor_get_uint16(val, sizeof(void*)*3 + 40)`
* `S.sc16_2` - `lean_ctor_get_uint16(val, sizeof(void*)*3 + 42)`
* `S.sc8_1` - `lean_ctor_get_uint8(val, sizeof(void*)*3 + 44)`
* `S.sc8_2` - `lean_ctor_get_uint8(val, sizeof(void*)*3 + 45)`
### Borrowing

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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?"

View File

@@ -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

View File

@@ -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

View File

@@ -5,7 +5,7 @@
"type": "git",
"subDir": "backend",
"scope": "",
"rev": "e8127fc6554b99fb988ecdceb770a5e112afbe24",
"rev": "3e8aabdea58c11813c5d3b7eeb187ded44ee9a34",
"name": "grove",
"manifestFile": "lake-manifest.json",
"inputRev": "master",

View File

@@ -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

View File

@@ -3,6 +3,32 @@ import sys
import subprocess
import requests
def check_gh_auth():
"""Check if GitHub CLI is properly authenticated."""
try:
result = subprocess.run(["gh", "auth", "status"], capture_output=True, text=True)
if result.returncode != 0:
return False, result.stderr
return True, None
except FileNotFoundError:
return False, "GitHub CLI (gh) is not installed. Please install it first."
except Exception as e:
return False, f"Error checking authentication: {e}"
def handle_gh_error(error_output):
"""Handle GitHub CLI errors and provide helpful messages."""
if "Not Found (HTTP 404)" in error_output:
return "Repository not found or access denied. Please check:\n" \
"1. The repository name is correct\n" \
"2. You have access to the repository\n" \
"3. Your GitHub CLI authentication is valid"
elif "Bad credentials" in error_output or "invalid" in error_output.lower():
return "Authentication failed. Please run 'gh auth login' to re-authenticate."
elif "rate limit" in error_output.lower():
return "GitHub API rate limit exceeded. Please try again later."
else:
return f"GitHub API error: {error_output}"
def main():
if len(sys.argv) != 4:
print("Usage: ./push_repo_release_tag.py <repo> <branch> <version_tag>")
@@ -14,6 +40,13 @@ def main():
print(f"Error: Branch '{branch}' is not 'master' or 'main'.")
sys.exit(1)
# Check GitHub CLI authentication first
auth_ok, auth_error = check_gh_auth()
if not auth_ok:
print(f"Authentication error: {auth_error}")
print("\nTo fix this, run: gh auth login")
sys.exit(1)
# Get the `lean-toolchain` file content
lean_toolchain_url = f"https://raw.githubusercontent.com/{repo}/{branch}/lean-toolchain"
try:
@@ -43,12 +76,23 @@ def main():
for tag in existing_tags:
print(tag.replace("refs/tags/", ""))
sys.exit(1)
elif list_tags_output.returncode != 0:
# Handle API errors when listing tags
error_msg = handle_gh_error(list_tags_output.stderr)
print(f"Error checking existing tags: {error_msg}")
sys.exit(1)
# Get the SHA of the branch
get_sha_cmd = [
"gh", "api", f"repos/{repo}/git/ref/heads/{branch}", "--jq", ".object.sha"
]
sha_result = subprocess.run(get_sha_cmd, capture_output=True, text=True, check=True)
sha_result = subprocess.run(get_sha_cmd, capture_output=True, text=True)
if sha_result.returncode != 0:
error_msg = handle_gh_error(sha_result.stderr)
print(f"Error getting branch SHA: {error_msg}")
sys.exit(1)
sha = sha_result.stdout.strip()
# Create the tag
@@ -58,11 +102,20 @@ def main():
"-F", f"ref=refs/tags/{version_tag}",
"-F", f"sha={sha}"
]
subprocess.run(create_tag_cmd, capture_output=True, text=True, check=True)
create_result = subprocess.run(create_tag_cmd, capture_output=True, text=True)
if create_result.returncode != 0:
error_msg = handle_gh_error(create_result.stderr)
print(f"Error creating tag: {error_msg}")
sys.exit(1)
print(f"Successfully created and pushed tag '{version_tag}' to {repo}.")
except subprocess.CalledProcessError as e:
print(f"Error while creating/pushing tag: {e.stderr.strip() if e.stderr else e}")
error_msg = handle_gh_error(e.stderr.strip() if e.stderr else str(e))
print(f"Error while creating/pushing tag: {error_msg}")
sys.exit(1)
except Exception as e:
print(f"Unexpected error: {e}")
sys.exit(1)
if __name__ == "__main__":

View File

@@ -231,6 +231,43 @@ def get_next_version(version):
# Next version is always .0
return f"v{major}.{minor + 1}.0"
def get_latest_nightly_tag(github_token):
"""Get the most recent nightly tag from leanprover/lean4-nightly."""
api_url = "https://api.github.com/repos/leanprover/lean4-nightly/tags"
headers = {'Authorization': f'token {github_token}'} if github_token else {}
response = requests.get(api_url, headers=headers)
if response.status_code != 200:
return None
tags = response.json()
if not tags:
return None
# Return the most recent tag name
return tags[0]['name']
def update_lean_toolchain_in_branch(org_repo, branch, toolchain_content, github_token):
"""Update the lean-toolchain file in a specific branch."""
api_url = f"https://api.github.com/repos/{org_repo}/contents/lean-toolchain"
headers = {'Authorization': f'token {github_token}'} if github_token else {}
# First get the current file to get its SHA
response = requests.get(f"{api_url}?ref={branch}", headers=headers)
if response.status_code != 200:
return False
current_file = response.json()
file_sha = current_file['sha']
# Update the file
update_data = {
"message": f"chore: update lean-toolchain to {toolchain_content}",
"content": base64.b64encode(toolchain_content.encode('utf-8')).decode('utf-8'),
"sha": file_sha,
"branch": branch
}
response = requests.put(api_url, json=update_data, headers=headers)
return response.status_code in [200, 201]
def check_bump_branch_toolchain(url, bump_branch, github_token):
"""Check if the lean-toolchain file in bump branch starts with either 'leanprover/lean4:nightly-' or the next version."""
content = get_branch_content(url, bump_branch, "lean-toolchain", github_token)
@@ -262,6 +299,61 @@ def pr_exists_with_title(repo_url, title, github_token):
return pr['number'], pr['html_url']
return None
def check_proofwidgets4_release(repo_url, target_toolchain, github_token):
"""Check if ProofWidgets4 has a release tag that uses the target toolchain."""
api_base = repo_url.replace("https://github.com/", "https://api.github.com/repos/")
headers = {'Authorization': f'token {github_token}'} if github_token else {}
# Get all tags matching v0.0.* pattern
response = requests.get(f"{api_base}/git/matching-refs/tags/v0.0.", headers=headers)
if response.status_code != 200:
print(f" ❌ Could not fetch ProofWidgets4 tags")
return False
tags = response.json()
if not tags:
print(f" ❌ No v0.0.* tags found for ProofWidgets4")
return False
# Extract tag names and sort by version number (descending)
tag_names = []
for tag in tags:
ref = tag['ref']
if ref.startswith('refs/tags/v0.0.'):
tag_name = ref.replace('refs/tags/', '')
try:
# Extract the number after v0.0.
version_num = int(tag_name.split('.')[-1])
tag_names.append((version_num, tag_name))
except (ValueError, IndexError):
continue
if not tag_names:
print(f" ❌ No valid v0.0.* tags found for ProofWidgets4")
return False
# Sort by version number (descending) and take the most recent 10
tag_names.sort(reverse=True)
recent_tags = tag_names[:10]
# Check each recent tag to see if it uses the target toolchain
for version_num, tag_name in recent_tags:
toolchain_content = get_branch_content(repo_url, tag_name, "lean-toolchain", github_token)
if toolchain_content is None:
continue
if is_version_gte(toolchain_content.strip(), target_toolchain):
print(f" ✅ Found release {tag_name} using compatible toolchain (>= {target_toolchain})")
return True
# If we get here, no recent release uses the target toolchain
# Find the highest version number to suggest the next one
highest_version = max(version_num for version_num, _ in recent_tags)
next_version = highest_version + 1
print(f" ❌ No recent ProofWidgets4 release uses toolchain >= {target_toolchain}")
print(f" You will need to create and push a tag v0.0.{next_version}")
return False
def main():
parser = argparse.ArgumentParser(description="Check release status of Lean4 repositories")
parser.add_argument("toolchain", help="The toolchain version to check (e.g., v4.6.0)")
@@ -386,6 +478,12 @@ def main():
continue
print(f" ✅ On compatible toolchain (>= {toolchain})")
# Special handling for ProofWidgets4
if name == "ProofWidgets4":
if not check_proofwidgets4_release(url, toolchain, github_token):
repo_status[name] = False
continue
if check_tag:
tag_exists_initially = tag_exists(url, toolchain, github_token)
if not tag_exists_initially:
@@ -394,7 +492,7 @@ def main():
repo_status[name] = False
continue
else:
print(f" Tag {toolchain} does not exist. Running `script/push_repo_release_tag.py {org_repo} {branch} {toolchain}`...")
print(f" Tag {toolchain} does not exist. Running `script/push_repo_release_tag.py {org_repo} {branch} {toolchain}`...")
# Run the script to create the tag
subprocess.run(["script/push_repo_release_tag.py", org_repo, branch, toolchain])
@@ -417,7 +515,7 @@ def main():
repo_status[name] = False
continue
else:
print(f" Tag {toolchain} is not merged into stable. Running `script/merge_remote.py {org_repo} stable {toolchain}`...")
print(f" Tag {toolchain} is not merged into stable. Running `script/merge_remote.py {org_repo} stable {toolchain}`...")
# Run the script to merge the tag
subprocess.run(["script/merge_remote.py", org_repo, "stable", toolchain])
@@ -434,19 +532,49 @@ def main():
if check_bump:
next_version = get_next_version(toolchain)
bump_branch = f"bump/{next_version}"
if not branch_exists(url, bump_branch, github_token):
# For mathlib4, use the nightly-testing fork for bump branches
bump_org_repo = org_repo
bump_url = url
if name == "mathlib4":
bump_org_repo = "leanprover-community/mathlib4-nightly-testing"
bump_url = "https://github.com/leanprover-community/mathlib4-nightly-testing"
branch_created = False
if not branch_exists(bump_url, bump_branch, github_token):
if args.dry_run:
print(f" ❌ Bump branch {bump_branch} does not exist. Run `gh api -X POST /repos/{org_repo}/git/refs -f ref=refs/heads/{bump_branch} -f sha=$(gh api /repos/{org_repo}/git/refs/heads/{branch} --jq .object.sha)` to create it.")
latest_nightly = get_latest_nightly_tag(github_token)
nightly_note = f" (will set lean-toolchain to {latest_nightly})" if name in ["batteries", "mathlib4"] and latest_nightly else ""
print(f" ❌ Bump branch {bump_branch} does not exist. Run `gh api -X POST /repos/{bump_org_repo}/git/refs -f ref=refs/heads/{bump_branch} -f sha=$(gh api /repos/{org_repo}/git/refs/heads/{branch} --jq .object.sha)` to create it{nightly_note}.")
repo_status[name] = False
continue
print(f" Bump branch {bump_branch} does not exist. Creating it...")
result = run_command(f"gh api -X POST /repos/{org_repo}/git/refs -f ref=refs/heads/{bump_branch} -f sha=$(gh api /repos/{org_repo}/git/refs/heads/{branch} --jq .object.sha)", check=False)
print(f" Bump branch {bump_branch} does not exist. Creating it...")
result = run_command(f"gh api -X POST /repos/{bump_org_repo}/git/refs -f ref=refs/heads/{bump_branch} -f sha=$(gh api /repos/{org_repo}/git/refs/heads/{branch} --jq .object.sha)", check=False)
if result.returncode != 0:
print(f" ❌ Failed to create bump branch {bump_branch}")
repo_status[name] = False
continue
branch_created = True
print(f" ✅ Bump branch {bump_branch} exists")
if not check_bump_branch_toolchain(url, bump_branch, github_token):
# For batteries and mathlib4, update the lean-toolchain to the latest nightly
if branch_created and name in ["batteries", "mathlib4"]:
latest_nightly = get_latest_nightly_tag(github_token)
if latest_nightly:
nightly_toolchain = f"leanprover/lean4:{latest_nightly}"
print(f" ⮕ Updating lean-toolchain to {nightly_toolchain}...")
if update_lean_toolchain_in_branch(bump_org_repo, bump_branch, nightly_toolchain, github_token):
print(f" ✅ Updated lean-toolchain to {nightly_toolchain}")
else:
print(f" ❌ Failed to update lean-toolchain to {nightly_toolchain}")
repo_status[name] = False
continue
else:
print(f" ❌ Could not fetch latest nightly tag")
repo_status[name] = False
continue
if not check_bump_branch_toolchain(bump_url, bump_branch, github_token):
repo_status[name] = False
continue

View File

@@ -1,10 +1,10 @@
#!/usr/bin/env python3
"""
Generate release steps script for Lean4 repositories.
Execute release steps for Lean4 repositories.
This script helps automate the release process for Lean4 and its dependent repositories
by generating step-by-step instructions for updating toolchains, creating tags,
by actually executing the step-by-step instructions for updating toolchains, creating tags,
and managing branches.
Usage:
@@ -12,11 +12,11 @@ Usage:
Arguments:
version: The version to set in the lean-toolchain file (e.g., v4.6.0)
repo: A substring of the repository name as specified in release_repos.yml
repo: The repository name as specified in release_repos.yml
Example:
python3 release_steps.py v4.6.0 mathlib
python3 release_steps.py v4.6.0 batt
python3 release_steps.py v4.6.0 mathlib4
python3 release_steps.py v4.6.0 batteries
The script reads repository configurations from release_repos.yml in the same directory.
Each repository may have specific requirements for:
@@ -32,23 +32,124 @@ import yaml
import os
import sys
import re
import subprocess
import shutil
import json
from pathlib import Path
# Color functions for terminal output
def blue(text):
"""Blue text for 'I'm doing something' messages."""
return f"\033[94m{text}\033[0m"
def green(text):
"""Green text for 'successful step' messages."""
return f"\033[92m{text}\033[0m"
def red(text):
"""Red text for 'this looks bad' messages."""
return f"\033[91m{text}\033[0m"
def yellow(text):
"""Yellow text for warnings."""
return f"\033[93m{text}\033[0m"
def run_command(cmd, cwd=None, check=True, stream_output=False):
"""Run a shell command and return the result."""
print(blue(f"Running: {cmd}"))
try:
if stream_output:
# Stream output in real-time for long-running commands
result = subprocess.run(cmd, shell=True, cwd=cwd, check=check, text=True)
return result
else:
# Capture output for commands where we need to process the result
result = subprocess.run(cmd, shell=True, cwd=cwd, check=check,
capture_output=True, text=True)
if result.stdout:
# Command output in plain white (default terminal color)
print(result.stdout)
return result
except subprocess.CalledProcessError as e:
print(red(f"Error running command: {cmd}"))
print(red(f"Exit code: {e.returncode}"))
if not stream_output:
print(f"Stdout: {e.stdout}")
print(f"Stderr: {e.stderr}")
raise
def load_repos_config(file_path):
with open(file_path, "r") as f:
return yaml.safe_load(f)["repositories"]
def find_repo(repo_substring, config):
pattern = re.compile(re.escape(repo_substring), re.IGNORECASE)
matching_repos = [r for r in config if pattern.search(r["name"])]
def find_repo(repo_name, config):
matching_repos = [r for r in config if r["name"] == repo_name]
if not matching_repos:
print(f"Error: No repository matching '{repo_substring}' found in configuration.")
sys.exit(1)
if len(matching_repos) > 1:
print(f"Error: Multiple repositories matching '{repo_substring}' found in configuration: {', '.join(r['name'] for r in matching_repos)}")
print(red(f"Error: No repository named '{repo_name}' found in configuration."))
available_repos = [r["name"] for r in config]
print(yellow(f"Available repositories: {', '.join(available_repos)}"))
sys.exit(1)
return matching_repos[0]
def generate_script(repo, version, config):
def setup_downstream_releases_dir():
"""Create the downstream_releases directory if it doesn't exist."""
downstream_dir = Path("downstream_releases")
if not downstream_dir.exists():
print(blue(f"Creating {downstream_dir} directory..."))
downstream_dir.mkdir()
print(green(f"Created {downstream_dir} directory"))
return downstream_dir
def clone_or_update_repo(repo_url, repo_dir, downstream_dir):
"""Clone the repository if it doesn't exist, or update it if it does."""
repo_path = downstream_dir / repo_dir
if repo_path.exists():
print(blue(f"Repository {repo_dir} already exists, updating..."))
run_command("git fetch", cwd=repo_path)
print(green(f"Updated repository {repo_dir}"))
else:
print(blue(f"Cloning {repo_url} to {repo_path}..."))
run_command(f"git clone {repo_url}", cwd=downstream_dir)
print(green(f"Cloned repository {repo_dir}"))
return repo_path
def get_remotes_for_repo(repo_name):
"""Get the appropriate remotes for bump and nightly-testing branches based on repository."""
if repo_name == "mathlib4":
return "nightly-testing", "nightly-testing"
else:
return "origin", "origin"
def check_and_abort_merge(repo_path):
"""Check if repository is in the middle of a merge and abort it if so."""
merge_head_file = repo_path / ".git" / "MERGE_HEAD"
if merge_head_file.exists():
print(yellow(f"Repository {repo_path.name} is in the middle of a merge. Aborting merge..."))
run_command("git merge --abort", cwd=repo_path)
print(green("Merge aborted successfully"))
return True
# Also check git status for other merge-related states
try:
result = run_command("git status --porcelain=v1", cwd=repo_path, check=False)
if result.returncode == 0:
# Check for unmerged paths (indicated by 'UU', 'AA', etc. in git status)
for line in result.stdout.splitlines():
if len(line) >= 2 and line[:2] in ['UU', 'AA', 'DD', 'AU', 'UA', 'DU', 'UD']:
print(yellow(f"Repository {repo_path.name} has unmerged paths. Aborting merge..."))
run_command("git merge --abort", cwd=repo_path)
print(green("Merge aborted successfully"))
return True
except subprocess.CalledProcessError:
# If git status fails, we'll let the main process handle it
pass
return False
def execute_release_steps(repo, version, config):
repo_config = find_repo(repo, config)
repo_name = repo_config['name']
repo_url = repo_config['url']
@@ -59,92 +160,481 @@ def generate_script(repo, version, config):
requires_tagging = repo_config.get("toolchain-tag", True)
has_stable_branch = repo_config.get("stable-branch", True)
script_lines = [
f"cd {repo_dir}",
"git fetch",
f"git checkout {default_branch} && git pull",
f"git checkout -b bump_to_{version}",
f"echo leanprover/lean4:{version} > lean-toolchain",
]
# Setup downstream releases directory
downstream_dir = setup_downstream_releases_dir()
# Clone or update the repository
repo_path = clone_or_update_repo(repo_url, repo_dir, downstream_dir)
# Special remote setup for mathlib4
if repo_name == "mathlib4":
print(blue("Setting up special remotes for mathlib4..."))
try:
# Check if nightly-testing remote already exists
result = run_command("git remote get-url nightly-testing", cwd=repo_path, check=False)
if result.returncode != 0:
# Add the nightly-testing remote
run_command("git remote add nightly-testing https://github.com/leanprover-community/mathlib4-nightly-testing.git", cwd=repo_path)
print(green("Added nightly-testing remote"))
else:
print(green("nightly-testing remote already exists"))
# Fetch from the nightly-testing remote
run_command("git fetch nightly-testing", cwd=repo_path)
print(green("Fetched from nightly-testing remote"))
except subprocess.CalledProcessError as e:
print(red(f"Error setting up mathlib4 remotes: {e}"))
print(yellow("Continuing with default remote setup..."))
print(blue(f"\n=== Executing release steps for {repo_name} ==="))
# Check if repository is in the middle of a merge and abort it if necessary
check_and_abort_merge(repo_path)
# Execute the release steps
run_command(f"git checkout {default_branch} && git pull", cwd=repo_path)
# Special rc1 safety check for batteries and mathlib4 (before creating any branches)
if repo_name in ["batteries", "mathlib4"] and version.endswith('-rc1'):
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]}..."))
# Get the base version (e.g., v4.6.0 from v4.6.0-rc1)
base_version = version.split('-rc')[0]
bump_branch = f"bump/{base_version}"
# Determine which remote to use for bump and nightly-testing branches
bump_remote, nightly_remote = get_remotes_for_repo(repo_name)
try:
# Fetch latest changes from the appropriate remote
run_command(f"git fetch {bump_remote}", cwd=repo_path)
# Check if the bump branch exists
result = run_command(f"git show-ref --verify --quiet refs/remotes/{bump_remote}/{bump_branch}", cwd=repo_path, check=False)
if result.returncode != 0:
print(red(f"Bump branch {bump_remote}/{bump_branch} does not exist. Cannot perform safety check."))
print(yellow("Please ensure the bump branch exists before proceeding."))
return
# Create a temporary branch for testing the merge
temp_branch = f"temp-merge-test-{base_version}"
# Clean up any existing temp branch from previous runs
result = run_command(f"git show-ref --verify --quiet refs/heads/{temp_branch}", cwd=repo_path, check=False)
if result.returncode == 0:
print(blue(f"Cleaning up existing temp branch {temp_branch}..."))
# Make sure we're not on the temp branch before deleting it
run_command(f"git checkout {default_branch}", cwd=repo_path)
run_command(f"git branch -D {temp_branch}", cwd=repo_path)
print(green(f"Deleted existing temp branch {temp_branch}"))
run_command(f"git checkout -b {temp_branch} {bump_remote}/{bump_branch}", cwd=repo_path)
# Try to merge nightly-testing
try:
run_command(f"git merge {nightly_remote}/nightly-testing", cwd=repo_path)
# Check what files have changed compared to the bump branch
changed_files = run_command(f"git diff --name-only {bump_remote}/{bump_branch}..HEAD", cwd=repo_path)
# Filter out allowed changes
allowed_patterns = ['lean-toolchain', 'lake-manifest.json']
problematic_files = []
for file in changed_files.stdout.strip().split('\n'):
if file.strip(): # Skip empty lines
is_allowed = any(pattern in file for pattern in allowed_patterns)
if not is_allowed:
problematic_files.append(file)
# Clean up temporary branch and return to default branch
run_command(f"git checkout {default_branch}", cwd=repo_path)
run_command(f"git branch -D {temp_branch}", cwd=repo_path)
if problematic_files:
print(red("❌ Safety check failed!"))
print(red(f"Merging nightly-testing into {bump_branch} would result in changes to:"))
for file in problematic_files:
print(red(f" - {file}"))
print(yellow("\nYou need to make a PR merging the changes from nightly-testing into the bump branch first."))
print(yellow(f"Create a PR from nightly-testing targeting {bump_branch} to resolve these changes."))
return
else:
print(green("✅ Safety check passed - only lean-toolchain and/or lake-manifest.json would change"))
except subprocess.CalledProcessError:
# Merge failed due to conflicts - check which files are conflicted
print(blue("Merge failed, checking which files are affected..."))
# Get all changed files using git status
status_result = run_command("git status --porcelain", cwd=repo_path)
changed_files = []
for line in status_result.stdout.splitlines():
if line.strip(): # Skip empty lines
# Extract filename (skip the first 3 characters which are status codes)
changed_files.append(line[3:])
# Filter out allowed files
allowed_patterns = ['lean-toolchain', 'lake-manifest.json']
problematic_files = []
for file in changed_files:
is_allowed = any(pattern in file for pattern in allowed_patterns)
if not is_allowed:
problematic_files.append(file)
if problematic_files:
# There are changes in non-allowed files - fail the safety check
# First abort the merge to clean up the conflicted state
run_command("git merge --abort", cwd=repo_path)
run_command(f"git checkout {default_branch}", cwd=repo_path)
run_command(f"git branch -D {temp_branch}", cwd=repo_path)
print(red("❌ Safety check failed!"))
print(red(f"Merging nightly-testing into {bump_branch} would result in changes to:"))
for file in problematic_files:
print(red(f" - {file}"))
print(yellow("\nYou need to make a PR merging the changes from nightly-testing into the bump branch first."))
print(yellow(f"Create a PR from nightly-testing targeting {bump_branch} to resolve these changes."))
return
else:
# Only allowed files are changed - resolve them and continue
print(green(f"✅ Only allowed files changed: {', '.join(changed_files)}"))
print(blue("Resolving conflicts by taking nightly-testing version..."))
# For each changed allowed file, take the nightly-testing version
for file in changed_files:
run_command(f"git checkout --theirs {file}", cwd=repo_path)
# Complete the merge
run_command("git add .", cwd=repo_path)
run_command("git commit --no-edit", cwd=repo_path)
print(green("✅ Safety check passed - changes only in allowed files"))
# Clean up temporary branch and return to default branch
run_command(f"git checkout {default_branch}", cwd=repo_path)
run_command(f"git branch -D {temp_branch}", cwd=repo_path)
except subprocess.CalledProcessError as e:
# Ensure we're back on the default branch even if setup failed
try:
run_command(f"git checkout {default_branch}", cwd=repo_path)
except subprocess.CalledProcessError:
print(red(f"Cannot return to {default_branch} branch. Repository is in an inconsistent state."))
print(red("Please manually check the repository state and fix any issues."))
return
print(red(f"Error during safety check: {e}"))
print(yellow("Skipping safety check and proceeding with normal merge..."))
# Check if the branch already exists
branch_name = f"bump_to_{version}"
try:
# Check if branch exists locally
result = run_command(f"git show-ref --verify --quiet refs/heads/{branch_name}", cwd=repo_path, check=False)
if result.returncode == 0:
print(blue(f"Branch {branch_name} already exists, checking it out..."))
run_command(f"git checkout {branch_name}", cwd=repo_path)
print(green(f"Checked out existing branch {branch_name}"))
else:
print(blue(f"Creating new branch {branch_name}..."))
run_command(f"git checkout -b {branch_name}", cwd=repo_path)
print(green(f"Created new branch {branch_name}"))
except subprocess.CalledProcessError:
print(blue(f"Creating new branch {branch_name}..."))
run_command(f"git checkout -b {branch_name}", cwd=repo_path)
print(green(f"Created new branch {branch_name}"))
# Update lean-toolchain
print(blue("Updating lean-toolchain file..."))
toolchain_file = repo_path / "lean-toolchain"
with open(toolchain_file, "w") as f:
f.write(f"leanprover/lean4:{version}\n")
print(green(f"Updated lean-toolchain to leanprover/lean4:{version}"))
# Special cases for specific repositories
if repo_name == "repl":
script_lines.extend([
"lake update",
"cd test/Mathlib",
f"perl -pi -e 's/rev = \"v\\d+\\.\\d+\\.\\d+(-rc\\d+)?\"/rev = \"{version}\"/g' lakefile.toml",
f"echo leanprover/lean4:{version} > lean-toolchain",
"lake update",
"cd ../..",
"./test.sh"
])
run_command("lake update", cwd=repo_path, stream_output=True)
mathlib_test_dir = repo_path / "test" / "Mathlib"
run_command(f'perl -pi -e \'s/rev = "v\\d+\\.\\d+\\.\\d+(-rc\\d+)?"/rev = "{version}"/g\' lakefile.toml', cwd=mathlib_test_dir)
# Update lean-toolchain in test/Mathlib
print(blue("Updating test/Mathlib/lean-toolchain..."))
mathlib_toolchain = mathlib_test_dir / "lean-toolchain"
with open(mathlib_toolchain, "w") as f:
f.write(f"leanprover/lean4:{version}\n")
print(green(f"Updated test/Mathlib/lean-toolchain to leanprover/lean4:{version}"))
run_command("lake update", cwd=mathlib_test_dir, stream_output=True)
try:
result = run_command("./test.sh", cwd=repo_path, stream_output=True, check=False)
if result.returncode == 0:
print(green("Tests completed successfully"))
else:
print(red("Tests failed, but continuing with PR creation..."))
print(red(f"Test exit code: {result.returncode}"))
except subprocess.CalledProcessError as e:
print(red("Tests failed, but continuing with PR creation..."))
print(red(f"Test error: {e}"))
elif dependencies:
script_lines.append('perl -pi -e \'s/"v4\\.[0-9]+(\\.[0-9]+)?(-rc[0-9]+)?"/"' + version + '"/g\' lakefile.*')
script_lines.append("lake update")
run_command(f'perl -pi -e \'s/"v4\\.[0-9]+(\\.[0-9]+)?(-rc[0-9]+)?"/"' + version + '"/g\' lakefile.*', cwd=repo_path)
run_command("lake update", cwd=repo_path, stream_output=True)
script_lines.append("")
# Commit changes (only if there are changes)
print(blue("Checking for changes to commit..."))
try:
# Check if there are any changes to commit (staged or unstaged)
result = run_command("git status --porcelain", cwd=repo_path, check=False)
if result.stdout.strip(): # There are changes
print(blue("Committing changes..."))
run_command(f'git commit -am "chore: bump toolchain to {version}"', cwd=repo_path)
print(green(f"Committed changes: chore: bump toolchain to {version}"))
else:
print(green("No changes to commit - toolchain already up to date"))
except subprocess.CalledProcessError:
print(yellow("Failed to check for changes, attempting commit anyway..."))
try:
run_command(f'git commit -am "chore: bump toolchain to {version}"', cwd=repo_path)
except subprocess.CalledProcessError as e:
if "nothing to commit" in e.stderr:
print(green("No changes to commit - toolchain already up to date"))
else:
raise
script_lines.extend([
f'git commit -am "chore: bump toolchain to {version}"',
""
])
# Handle special merging cases
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
bump_remote, nightly_remote = get_remotes_for_repo(repo_name)
# Fetch latest changes to ensure we have the most up-to-date bump branch
print(blue(f"Fetching latest changes from {bump_remote}..."))
run_command(f"git fetch {bump_remote}", cwd=repo_path)
try:
print(blue(f"Merging {bump_remote}/bump/{version.split('-rc')[0]}..."))
run_command(f"git merge {bump_remote}/bump/{version.split('-rc')[0]}", cwd=repo_path)
print(green("Merge completed successfully"))
except subprocess.CalledProcessError:
# Merge failed due to conflicts - check which files are conflicted
print(blue("Merge conflicts detected, checking which files are affected..."))
# Get conflicted files using git status
status_result = run_command("git status --porcelain", cwd=repo_path)
conflicted_files = []
for line in status_result.stdout.splitlines():
if len(line) >= 2 and line[:2] in ['UU', 'AA', 'DD', 'AU', 'UA', 'DU', 'UD']:
# Extract filename (skip the first 3 characters which are status codes)
conflicted_files.append(line[3:])
# Filter out allowed files
allowed_patterns = ['lean-toolchain', 'lake-manifest.json']
problematic_files = []
for file in conflicted_files:
is_allowed = any(pattern in file for pattern in allowed_patterns)
if not is_allowed:
problematic_files.append(file)
if problematic_files:
# There are conflicts in non-allowed files - fail
print(red("❌ Merge failed!"))
print(red(f"Merging {bump_remote}/bump/{version.split('-rc')[0]} resulted in conflicts in:"))
for file in problematic_files:
print(red(f" - {file}"))
print(red("Please resolve these conflicts manually."))
return
else:
# Only allowed files are conflicted - resolve them automatically
print(green(f"✅ Only allowed files conflicted: {', '.join(conflicted_files)}"))
print(blue("Resolving conflicts automatically..."))
# Overwrite lean-toolchain with our target version
if 'lean-toolchain' in conflicted_files:
print(blue(f"Overwriting lean-toolchain with target version {version}"))
toolchain_file = repo_path / "lean-toolchain"
with open(toolchain_file, "w") as f:
f.write(f"leanprover/lean4:{version}\n")
# For other allowed files, take our version (since we want our changes)
for file in conflicted_files:
if file != 'lean-toolchain':
run_command(f"git checkout --ours {file}", cwd=repo_path)
# Run lake update to rebuild lake-manifest.json
print(blue("Running lake update to rebuild lake-manifest.json..."))
run_command("lake update", cwd=repo_path, stream_output=True)
# Complete the merge
run_command("git add .", cwd=repo_path)
run_command("git commit --no-edit", cwd=repo_path)
print(green("✅ Merge completed successfully with automatic conflict resolution"))
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."))
# Fetch latest changes to ensure we have the most up-to-date nightly-testing branch
print(blue("Fetching latest changes from origin..."))
run_command("git fetch origin", cwd=repo_path)
try:
print(blue("Merging origin/nightly-testing..."))
run_command("git merge origin/nightly-testing", cwd=repo_path)
print(green("Merge completed successfully"))
except subprocess.CalledProcessError:
# Merge failed due to conflicts - check which files are conflicted
print(blue("Merge conflicts detected, checking which files are affected..."))
# Get conflicted files using git status
status_result = run_command("git status --porcelain", cwd=repo_path)
conflicted_files = []
for line in status_result.stdout.splitlines():
if len(line) >= 2 and line[:2] in ['UU', 'AA', 'DD', 'AU', 'UA', 'DU', 'UD']:
# Extract filename (skip the first 3 characters which are status codes)
conflicted_files.append(line[3:])
# Filter out allowed files
allowed_patterns = ['lean-toolchain', 'lake-manifest.json']
problematic_files = []
for file in conflicted_files:
is_allowed = any(pattern in file for pattern in allowed_patterns)
if not is_allowed:
problematic_files.append(file)
if problematic_files:
# There are conflicts in non-allowed files - fail
print(red("❌ Merge failed!"))
print(red(f"Merging nightly-testing resulted in conflicts in:"))
for file in problematic_files:
print(red(f" - {file}"))
print(red("Please resolve these conflicts manually."))
return
else:
# Only allowed files are conflicted - resolve them automatically
print(green(f"✅ Only allowed files conflicted: {', '.join(conflicted_files)}"))
print(blue("Resolving conflicts automatically..."))
# For lean-toolchain and lake-manifest.json, keep our versions
for file in conflicted_files:
print(blue(f"Keeping our version of {file}"))
run_command(f"git checkout --ours {file}", cwd=repo_path)
# Complete the merge
run_command("git add .", cwd=repo_path)
run_command("git commit --no-edit", cwd=repo_path)
print(green("✅ Merge completed successfully with automatic conflict resolution"))
if re.search(r'rc\d+$', version) and repo_name in ["batteries", "mathlib4"]:
script_lines.extend([
"echo 'This repo has nightly-testing infrastructure'",
f"git merge origin/bump/{version.split('-rc')[0]}",
"echo 'Please resolve any conflicts.'",
"grep nightly-testing lakefile.* && echo 'Please ensure the lakefile does not include nightly-testing versions.'",
""
])
if re.search(r'rc\d+$', version) and repo_name in ["verso", "reference-manual"]:
script_lines.extend([
"echo 'This repo does development on nightly-testing: remember to rebase merge the PR.'",
f"git merge origin/nightly-testing",
"echo 'Please resolve any conflicts.'",
""
])
if repo_name != "Mathlib":
script_lines.extend([
"lake build && if lake check-test; then lake test; fi",
""
])
# Build and test (skip for Mathlib)
if repo_name not in ["mathlib4"]:
print(blue("Building project..."))
# Clean lake cache for a fresh build
print(blue("Cleaning lake cache..."))
run_command("rm -rf .lake", cwd=repo_path)
try:
run_command("lake build", cwd=repo_path, stream_output=True)
print(green("Build completed successfully"))
except subprocess.CalledProcessError as e:
print(red("Build failed, but continuing with PR creation..."))
print(red(f"Build error: {e}"))
# Check if lake check-test exists before running tests
print(blue("Running tests..."))
check_test_result = run_command("lake check-test", cwd=repo_path, check=False)
if check_test_result.returncode == 0:
try:
run_command("lake test", cwd=repo_path, stream_output=True)
print(green("Tests completed successfully"))
except subprocess.CalledProcessError as e:
print(red("Tests failed, but continuing with PR creation..."))
print(red(f"Test error: {e}"))
else:
print(yellow("lake check-test reports that there is no test suite"))
script_lines.extend([
'gh pr create --title "chore: bump toolchain to ' + version + '" --body ""',
"echo 'Please review the PR and merge or rebase it.'",
""
])
# Push the branch to remote before creating PR
print(blue("Checking remote branch status..."))
try:
# Check if branch exists on remote
result = run_command(f"git ls-remote --heads origin {branch_name}", cwd=repo_path, check=False)
if not result.stdout.strip():
print(blue(f"Pushing branch {branch_name} to remote..."))
run_command(f"git push -u origin {branch_name}", cwd=repo_path)
print(green(f"Successfully pushed branch {branch_name} to remote"))
else:
print(blue(f"Branch {branch_name} already exists on remote, pushing any new commits..."))
run_command(f"git push", cwd=repo_path)
print(green("Successfully pushed commits to remote"))
except subprocess.CalledProcessError:
print(red("Failed to push branch to remote. Please check your permissions and network connection."))
print(yellow(f"You may need to run: git push -u origin {branch_name}"))
return
return "\n".join(script_lines)
# Create pull request (only if one doesn't already exist)
print(blue("Checking for existing pull request..."))
try:
# Check if PR already exists for this branch
result = run_command(f'gh pr list --head {branch_name} --json number', cwd=repo_path, check=False)
if result.returncode == 0 and result.stdout.strip() != "[]":
print(green(f"Pull request already exists for branch {branch_name}"))
# Get the PR URL
pr_result = run_command(f'gh pr view {branch_name} --json url', cwd=repo_path, check=False)
if pr_result.returncode == 0:
pr_data = json.loads(pr_result.stdout)
print(green(f"PR URL: {pr_data.get('url', 'N/A')}"))
else:
# Create new PR
print(blue("Creating new pull request..."))
run_command(f'gh pr create --title "chore: bump toolchain to {version}" --body ""', cwd=repo_path)
print(green("Pull request created successfully!"))
except subprocess.CalledProcessError:
print(red("Failed to check for existing PR or create new PR."))
print(yellow("This could be due to:"))
print(yellow("1. GitHub CLI not authenticated"))
print(yellow("2. No push permissions to the repository"))
print(yellow("3. Network issues"))
print(f"Branch: {branch_name}")
print(f"Title: chore: bump toolchain to {version}")
print(yellow("Please create the PR manually if needed."))
def main():
parser = argparse.ArgumentParser(
description="Generate release steps script for Lean4 repositories.",
description="Execute release steps for Lean4 repositories.",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Examples:
%(prog)s v4.6.0 mathlib Generate steps for updating Mathlib to v4.6.0
%(prog)s v4.6.0 batt Generate steps for updating Batteries to v4.6.0
%(prog)s v4.6.0 mathlib4 Execute steps for updating Mathlib to v4.6.0
%(prog)s v4.6.0 batteries Execute steps for updating Batteries to v4.6.0
The script will generate shell commands to:
1. Update the lean-toolchain file
2. Create appropriate branches and commits
3. Create pull requests
The script will:
1. Create a downstream_releases/ directory
2. Clone or update the target repository
3. Update the lean-toolchain file
4. Create appropriate branches and commits
5. Build and test the project
6. Create pull requests
(Note that the steps of creating toolchain version tags, and merging these into `stable` branches,
are handled by `script/release_checklist.py`.)
"""
)
parser.add_argument("version", help="The version to set in the lean-toolchain file (e.g., v4.6.0)")
parser.add_argument("repo", help="A substring of the repository name as specified in release_repos.yml")
parser.add_argument("repo", help="The repository name as specified in release_repos.yml")
args = parser.parse_args()
config_path = os.path.join(os.path.dirname(__file__), "release_repos.yml")
config = load_repos_config(config_path)
script = generate_script(args.repo, args.version, config)
print(script)
execute_release_steps(args.repo, args.version, config)
if __name__ == "__main__":
main()

View File

@@ -10,7 +10,7 @@ endif()
include(ExternalProject)
project(LEAN CXX C)
set(LEAN_VERSION_MAJOR 4)
set(LEAN_VERSION_MINOR 22)
set(LEAN_VERSION_MINOR 23)
set(LEAN_VERSION_PATCH 0)
set(LEAN_VERSION_IS_RELEASE 0) # This number is 1 in the release revision, and 0 otherwise.
set(LEAN_SPECIAL_VERSION_DESC "" CACHE STRING "Additional version description like 'nightly-2018-03-11'")
@@ -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()

View File

@@ -6,41 +6,43 @@ Authors: Leonardo de Moura
module
prelude
import Init.Prelude
import Init.Notation
import Init.Tactics
import Init.TacticsExtra
import Init.ByCases
import Init.RCases
import Init.Core
import Init.Control
import Init.Data.Basic
import Init.WF
import Init.WFTactics
import Init.Data
import Init.System
import Init.Util
import Init.Dynamic
import Init.ShareCommon
import Init.MetaTypes
import Init.Meta
import Init.NotationExtra
import Init.SimpLemmas
import Init.PropLemmas
import Init.Hints
import Init.Conv
import Init.Guard
import Init.Simproc
import Init.SizeOfLemmas
import Init.BinderPredicates
import Init.Ext
import Init.Omega
import Init.MacroTrace
import Init.Grind
import Init.GrindInstances
import Init.While
import Init.Syntax
import Init.Internal
import Init.Try
import Init.BinderNameHint
import Init.Task
public import Init.Prelude
public import Init.Notation
public import Init.Tactics
public import Init.TacticsExtra
public import Init.ByCases
public import Init.RCases
public import Init.Core
public import Init.Control
public import Init.Data.Basic
public import Init.WF
public import Init.WFTactics
public import Init.Data
public import Init.System
public import Init.Util
public import Init.Dynamic
public import Init.ShareCommon
public import Init.MetaTypes
public import Init.Meta
public import Init.NotationExtra
public import Init.SimpLemmas
public import Init.PropLemmas
public import Init.Hints
public import Init.Conv
public import Init.Guard
public import Init.Simproc
public import Init.SizeOfLemmas
public import Init.BinderPredicates
public import Init.Ext
public import Init.Omega
public import Init.MacroTrace
public import Init.Grind
public import Init.GrindInstances
public import Init.While
public import Init.Syntax
public import Init.Internal
public import Init.Try
public import Init.BinderNameHint
public import Init.Task
public import Init.GetElem
public import Init.GetElemV

View File

@@ -16,6 +16,10 @@ universe u v
namespace Classical
/-- Using `Classical.choice`, extracts a term from a `Nonempty` type. -/
protected noncomputable abbrev arbitrary (α) [h : Nonempty α] : α :=
Classical.choice h
noncomputable def indefiniteDescription {α : Sort u} (p : α Prop) (h : x, p x) : {x // p x} :=
choice <| let x, px := h; x, px

View File

@@ -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}

View File

@@ -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

View File

@@ -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. -/
@@ -323,7 +323,7 @@ macro_rules
| `(conv| repeat $seq) => `(conv| first | ($seq); repeat $seq | skip)
/--
Extracts `let` and `let_fun` expressions from within the target expression.
Extracts `let` and `have` expressions from within the target expression.
This is the conv mode version of the `extract_lets` tactic.
- `extract_lets` extracts all the lets from the target.
@@ -336,7 +336,7 @@ See also `lift_lets`, which does not extract lets as local declarations.
syntax (name := extractLets) "extract_lets " optConfig (ppSpace colGt (ident <|> hole))* : conv
/--
Lifts `let` and `let_fun` expressions within the target expression as far out as possible.
Lifts `let` and `have` expressions within the target expression as far out as possible.
This is the conv mode version of the `lift_lets` tactic.
-/
syntax (name := liftLets) "lift_lets " optConfig : conv

View File

@@ -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

View File

@@ -10,7 +10,7 @@ prelude
public import Init.Classical
public import Init.ByCases
public section
@[expose] public section
namespace Lean.Data.AC
inductive Expr

View File

@@ -180,7 +180,7 @@ in-place when the reference to the array is unique.
This avoids overhead due to unboxing a `Nat` used as an index.
-/
@[extern "lean_array_uset"]
@[extern "lean_array_uset", expose]
def uset (xs : Array α) (i : USize) (v : α) (h : i.toNat < xs.size) : Array α :=
xs.set i.toNat v h
@@ -263,7 +263,7 @@ Examples:
* `#["red", "green", "blue", "brown"].swapIfInBounds 0 4 = #["red", "green", "blue", "brown"]`
* `#["red", "green", "blue", "brown"].swapIfInBounds 9 2 = #["red", "green", "blue", "brown"]`
-/
@[extern "lean_array_swap"]
@[extern "lean_array_swap", grind]
def swapIfInBounds (xs : Array α) (i j : @& Nat) : Array α :=
if h₁ : i < xs.size then
if h₂ : j < xs.size then swap xs i j
@@ -1024,7 +1024,7 @@ The optional parameters `start` and `stop` control the region of the array to wh
applied. Iteration proceeds from `start` (inclusive) to `stop` (exclusive), so `f` is not invoked
unless `start < stop`. By default, the entire array is used.
-/
@[inline]
@[inline, expose]
protected def forM {α : Type u} {m : Type v Type w} [Monad m] (f : α m PUnit) (as : Array α) (start := 0) (stop := as.size) : m PUnit :=
as.foldlM (fun _ => f) start stop
@@ -1808,6 +1808,7 @@ Examples:
* `#["apple", "pear", "orange"].eraseIdxIfInBounds 3 = #["apple", "pear", "orange"]`
* `#["apple", "pear", "orange"].eraseIdxIfInBounds 5 = #["apple", "pear", "orange"]`
-/
@[grind]
def eraseIdxIfInBounds (xs : Array α) (i : Nat) : Array α :=
if h : i < xs.size then xs.eraseIdx i h else xs
@@ -1918,6 +1919,7 @@ Examples:
* `#["tues", "thur", "sat"].insertIdxIfInBounds 3 "wed" = #["tues", "thur", "sat", "wed"]`
* `#["tues", "thur", "sat"].insertIdxIfInBounds 4 "wed" = #["tues", "thur", "sat"]`
-/
@[grind]
def insertIdxIfInBounds (as : Array α) (i : Nat) (a : α) : Array α :=
if h : i as.size then
insertIdx as i a

View File

@@ -382,11 +382,12 @@ theorem eraseIdx_ne_empty_iff {xs : Array α} {i : Nat} {h} : xs.eraseIdx i ≠
simp [h]
· simp
@[grind ]
theorem mem_of_mem_eraseIdx {xs : Array α} {i : Nat} {h} {a : α} (h : a xs.eraseIdx i) : a xs := by
rcases xs with xs
simpa using List.mem_of_mem_eraseIdx (by simpa using h)
grind_pattern mem_of_mem_eraseIdx => a xs.eraseIdx i
theorem eraseIdx_append_of_lt_size {xs : Array α} {k : Nat} (hk : k < xs.size) (ys : Array α) (h) :
eraseIdx (xs ++ ys) k = eraseIdx xs k ++ ys := by
rcases xs with l

View File

@@ -387,7 +387,7 @@ theorem find?_eq_some_iff_getElem {xs : Array α} {p : α → Bool} {b : α} :
/-! ### findIdx -/
@[grind =]
theorem findIdx_empty : findIdx p #[] = 0 := rfl
theorem findIdx_empty : findIdx p #[] = 0 := by simp
@[grind =]
theorem findIdx_singleton {a : α} {p : α Bool} :

View File

@@ -129,7 +129,7 @@ theorem none_eq_getElem?_iff {xs : Array α} {i : Nat} : none = xs[i]? ↔ xs.si
theorem getElem?_eq_none {xs : Array α} (h : xs.size i) : xs[i]? = none := by
simp [h]
grind_pattern Array.getElem?_eq_none => xs.size i, xs[i]?
grind_pattern Array.getElem?_eq_none => xs.size, xs[i]?
@[simp] theorem getElem?_eq_getElem {xs : Array α} {i : Nat} (h : i < xs.size) : xs[i]? = some xs[i] :=
getElem?_pos ..
@@ -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)
@@ -985,12 +985,13 @@ theorem mem_set {xs : Array α} {i : Nat} (h : i < xs.size) {a : α} :
simp [mem_iff_getElem]
exact i, (by simpa using h), by simp
@[grind ]
theorem mem_or_eq_of_mem_set
{xs : Array α} {i : Nat} {a b : α} {w : i < xs.size} (h : a xs.set i b) : a xs a = b := by
cases xs
simpa using List.mem_or_eq_of_mem_set (by simpa using h)
grind_pattern mem_or_eq_of_mem_set => a xs.set i b
/-! ### setIfInBounds -/
@[simp, grind] theorem setIfInBounds_empty {i : Nat} {a : α} :

View File

@@ -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

View File

@@ -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
@@ -19,28 +22,55 @@ namespace Array
/-! ### Lexicographic ordering -/
@[simp, grind =] theorem _root_.List.lt_toArray [LT α] {l₁ l₂ : List α} : l₁.toArray < l₂.toArray l₁ < l₂ := Iff.rfl
@[simp, grind =] theorem _root_.List.le_toArray [LT α] {l₁ l₂ : List α} : l₁.toArray l₂.toArray l₁ l₂ := Iff.rfl
@[simp] theorem _root_.List.lt_toArray [LT α] {l₁ l₂ : List α} : l₁.toArray < l₂.toArray l₁ < l₂ := Iff.rfl
@[simp] theorem _root_.List.le_toArray [LT α] {l₁ l₂ : List α} : l₁.toArray l₂.toArray l₁ l₂ := Iff.rfl
@[simp, grind =] theorem lt_toList [LT α] {xs ys : Array α} : xs.toList < ys.toList xs < ys := Iff.rfl
@[simp, grind =] theorem le_toList [LT α] {xs ys : Array α} : xs.toList ys.toList xs ys := Iff.rfl
@[simp] theorem lt_toList [LT α] {xs ys : Array α} : xs.toList < ys.toList xs < ys := Iff.rfl
@[simp] theorem le_toList [LT α] {xs ys : Array α} : xs.toList ys.toList xs ys := Iff.rfl
grind_pattern _root_.List.lt_toArray => l₁.toArray < l₂.toArray
grind_pattern _root_.List.le_toArray => l₁.toArray l₂.toArray
grind_pattern lt_toList => xs.toList < ys.toList
grind_pattern le_toList => xs.toList ys.toList
protected theorem not_lt_iff_ge [LT α] {xs ys : Array α} : ¬ xs < ys ys xs := Iff.rfl
protected theorem not_le_iff_gt [DecidableEq α] [LT α] [DecidableLT α] {xs ys : Array α} :
protected theorem not_le_iff_gt [LT α] {xs ys : Array α} :
¬ xs ys ys < xs :=
Decidable.not_not
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
@@ -49,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]
@@ -94,7 +131,7 @@ instance [LT α] [Trans (· < · : αα → Prop) (· < ·) (· < ·)] :
Trans (· < · : Array α Array α Prop) (· < ·) (· < ·) where
trans h₁ h₂ := Array.lt_trans h₁ h₂
protected theorem lt_of_le_of_lt [DecidableEq α] [LT α] [DecidableLT α]
protected theorem lt_of_le_of_lt [LT α]
[i₀ : Std.Irrefl (· < · : α α Prop)]
[i₁ : Std.Asymm (· < · : α α Prop)]
[i₂ : Std.Antisymm (¬ · < · : α α Prop)]
@@ -102,7 +139,7 @@ protected theorem lt_of_le_of_lt [DecidableEq α] [LT α] [DecidableLT α]
{xs ys zs : Array α} (h₁ : xs ys) (h₂ : ys < zs) : xs < zs :=
List.lt_of_le_of_lt h₁ h₂
protected theorem le_trans [DecidableEq α] [LT α] [DecidableLT α]
protected theorem le_trans [LT α]
[Std.Irrefl (· < · : α α Prop)]
[Std.Asymm (· < · : α α Prop)]
[Std.Antisymm (¬ · < · : α α Prop)]
@@ -110,7 +147,7 @@ protected theorem le_trans [DecidableEq α] [LT α] [DecidableLT α]
{xs ys zs : Array α} (h₁ : xs ys) (h₂ : ys zs) : xs zs :=
fun h₃ => h₁ (Array.lt_of_le_of_lt h₂ h₃)
instance [DecidableEq α] [LT α] [DecidableLT α]
instance [LT α]
[Std.Irrefl (· < · : α α Prop)]
[Std.Asymm (· < · : α α Prop)]
[Std.Antisymm (¬ · < · : α α Prop)]
@@ -122,34 +159,34 @@ protected theorem lt_asymm [LT α]
[i : Std.Asymm (· < · : α α Prop)]
{xs ys : Array α} (h : xs < ys) : ¬ ys < xs := List.lt_asymm h
instance [DecidableEq α] [LT α] [DecidableLT α]
instance [LT α]
[Std.Asymm (· < · : α α Prop)] :
Std.Asymm (· < · : Array α Array α Prop) where
asymm _ _ := Array.lt_asymm
protected theorem le_total [DecidableEq α] [LT α] [DecidableLT α]
protected theorem le_total [LT α]
[i : Std.Total (¬ · < · : α α Prop)] (xs ys : Array α) : xs ys ys xs :=
List.le_total xs.toList ys.toList
@[simp] protected theorem not_lt [LT α]
{xs ys : Array α} : ¬ xs < ys ys xs := Iff.rfl
@[simp] protected theorem not_le [DecidableEq α] [LT α] [DecidableLT α]
{xs ys : Array α} : ¬ ys xs xs < ys := Decidable.not_not
@[simp] protected theorem not_le [LT α]
{xs ys : Array α} : ¬ ys xs xs < ys := Classical.not_not
protected theorem le_of_lt [DecidableEq α] [LT α] [DecidableLT α]
protected theorem le_of_lt [LT α]
[i : Std.Total (¬ · < · : α α Prop)]
{xs ys : Array α} (h : xs < ys) : xs ys :=
List.le_of_lt h
protected theorem le_iff_lt_or_eq [DecidableEq α] [LT α] [DecidableLT α]
protected theorem le_iff_lt_or_eq [LT α]
[Std.Irrefl (· < · : α α Prop)]
[Std.Antisymm (¬ · < · : α α Prop)]
[Std.Total (¬ · < · : α α Prop)]
{xs ys : Array α} : xs ys xs < ys xs = ys := by
simpa using List.le_iff_lt_or_eq (l₁ := xs.toList) (l₂ := ys.toList)
instance [DecidableEq α] [LT α] [DecidableLT α]
instance [LT α]
[Std.Total (¬ · < · : α α Prop)] :
Std.Total (· · : Array α Array α Prop) where
total := Array.le_total
@@ -218,7 +255,7 @@ theorem lex_eq_false_iff_exists [BEq α] [PartialEquivBEq α] (lt : αα
cases l₂
simp_all [List.lex_eq_false_iff_exists]
protected theorem lt_iff_exists [DecidableEq α] [LT α] [DecidableLT α] {xs ys : Array α} :
protected theorem lt_iff_exists [LT α] {xs ys : Array α} :
xs < ys
(xs = ys.take xs.size xs.size < ys.size)
( (i : Nat) (h₁ : i < xs.size) (h₂ : i < ys.size),
@@ -228,7 +265,7 @@ protected theorem lt_iff_exists [DecidableEq α] [LT α] [DecidableLT α] {xs ys
cases ys
simp [List.lt_iff_exists]
protected theorem le_iff_exists [DecidableEq α] [LT α] [DecidableLT α]
protected theorem le_iff_exists [LT α]
[Std.Irrefl (· < · : α α Prop)]
[Std.Asymm (· < · : α α Prop)]
[Std.Antisymm (¬ · < · : α α Prop)] {xs ys : Array α} :
@@ -248,7 +285,7 @@ theorem append_left_lt [LT α] {xs ys zs : Array α} (h : ys < zs) :
cases zs
simpa using List.append_left_lt h
theorem append_left_le [DecidableEq α] [LT α] [DecidableLT α]
theorem append_left_le [LT α]
[Std.Irrefl (· < · : α α Prop)]
[Std.Asymm (· < · : α α Prop)]
[Std.Antisymm (¬ · < · : α α Prop)]
@@ -272,7 +309,7 @@ protected theorem map_lt [LT α] [LT β]
cases ys
simpa using List.map_lt w h
protected theorem map_le [DecidableEq α] [LT α] [DecidableLT α] [DecidableEq β] [LT β] [DecidableLT β]
protected theorem map_le [LT α] [LT β]
[Std.Irrefl (· < · : α α Prop)]
[Std.Asymm (· < · : α α Prop)]
[Std.Antisymm (¬ · < · : α α Prop)]

View File

@@ -6,7 +6,8 @@ Authors: Leonardo de Moura
module
prelude
public import Init.Data.Array.Basic
public import Init.GetElem
import Init.Data.Array.GetLit
public import Init.Data.Slice.Basic
public section
@@ -159,64 +160,10 @@ instance : EmptyCollection (Subarray α) :=
instance : Inhabited (Subarray α) :=
{}
/--
The run-time implementation of `ForIn.forIn` for `Subarray`, which allows it to be used with `for`
loops in `do`-notation.
This definition replaces `Subarray.forIn`.
/-!
`ForIn`, `foldlM`, `foldl` and other operations are implemented in `Init.Data.Slice.Array.Iterator`
using the slice iterator.
-/
@[inline] unsafe def forInUnsafe {α : Type u} {β : Type v} {m : Type v Type w} [Monad m] (s : Subarray α) (b : β) (f : α β m (ForInStep β)) : m β :=
let sz := USize.ofNat s.stop
let rec @[specialize] loop (i : USize) (b : β) : m β := do
if i < sz then
let a := s.array.uget i lcProof
match ( f a b) with
| ForInStep.done b => pure b
| ForInStep.yield b => loop (i+1) b
else
pure b
loop (USize.ofNat s.start) b
/--
The implementation of `ForIn.forIn` for `Subarray`, which allows it to be used with `for` loops in
`do`-notation.
-/
-- TODO: provide reference implementation
@[implemented_by Subarray.forInUnsafe]
protected opaque forIn {α : Type u} {β : Type v} {m : Type v Type w} [Monad m] (s : Subarray α) (b : β) (f : α β m (ForInStep β)) : m β :=
pure b
instance : ForIn m (Subarray α) α where
forIn := Subarray.forIn
/--
Folds a monadic operation from left to right over the elements in a subarray.
An accumulator of type `β` is constructed by starting with `init` and monadically combining each
element of the subarray with the current accumulator value in turn. The monad in question may permit
early termination or repetition.
Examples:
```lean example
#eval #["red", "green", "blue"].toSubarray.foldlM (init := "") fun acc x => do
let l ← Option.guard (· ≠ 0) x.length
return s!"{acc}({l}){x} "
```
```output
some "(3)red (5)green (4)blue "
```
```lean example
#eval #["red", "green", "blue"].toSubarray.foldlM (init := 0) fun acc x => do
let l ← Option.guard (· ≠ 5) x.length
return s!"{acc}({l}){x} "
```
```output
none
```
-/
@[inline]
def foldlM {α : Type u} {β : Type v} {m : Type v Type w} [Monad m] (f : β α m β) (init : β) (as : Subarray α) : m β :=
as.array.foldlM f (init := init) (start := as.start) (stop := as.stop)
/--
Folds a monadic operation from right to left over the elements in a subarray.
@@ -313,20 +260,6 @@ The elements are processed starting at the highest index and moving down.
def forRevM {α : Type u} {m : Type v Type w} [Monad m] (f : α m PUnit) (as : Subarray α) : m PUnit :=
as.array.forRevM f (start := as.stop) (stop := as.start)
/--
Folds an operation from left to right over the elements in a subarray.
An accumulator of type `β` is constructed by starting with `init` and combining each
element of the subarray with the current accumulator value in turn.
Examples:
* `#["red", "green", "blue"].toSubarray.foldl (· + ·.length) 0 = 12`
* `#["red", "green", "blue"].toSubarray.popFront.foldl (· + ·.length) 0 = 9`
-/
@[inline]
def foldl {α : Type u} {β : Type v} (f : β α β) (init : β) (as : Subarray α) : β :=
Id.run <| as.foldlM (pure <| f · ·) (init := init)
/--
Folds an operation from right to left over the elements in a subarray.
@@ -464,18 +397,6 @@ def toSubarray (as : Array α) (start : Nat := 0) (stop : Nat := as.size) : Suba
start_le_stop := Nat.le_refl _,
stop_le_array_size := Nat.le_refl _ }
/--
Allocates a new array that contains the contents of the subarray.
-/
@[coe]
def ofSubarray (s : Subarray α) : Array α := Id.run do
let mut as := mkEmpty (s.stop - s.start)
for a in s do
as := as.push a
return as
instance : Coe (Subarray α) (Array α) := ofSubarray
/-- A subarray with the provided bounds.-/
syntax:max term noWs "[" withoutPosition(term ":" term) "]" : term
/-- A subarray with the provided lower bound that extends to the rest of the array. -/
@@ -489,22 +410,3 @@ macro_rules
| `($a[$start : ]) => `(let a := $a; Array.toSubarray a $start a.size)
end Array
@[inherit_doc Array.ofSubarray]
def Subarray.toArray (s : Subarray α) : Array α :=
Array.ofSubarray s
instance : Append (Subarray α) where
append x y :=
let a := x.toArray ++ y.toArray
a.toSubarray 0 a.size
/-- `Subarray` representation. -/
protected def Subarray.repr [Repr α] (s : Subarray α) : Std.Format :=
repr s.toArray ++ ".toSubarray"
instance [Repr α] : Repr (Subarray α) where
reprPrec s _ := Subarray.repr s
instance [ToString α] : ToString (Subarray α) where
toString s := toString s.toArray

View File

@@ -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
@@ -35,7 +35,12 @@ protected def ofNatLt {n : Nat} (i : Nat) (p : i < 2 ^ n) : BitVec n :=
section Nat
instance natCastInst : NatCast (BitVec w) := BitVec.ofNat w
/--
`NatCast` instance for `BitVec`.
-/
-- As this is a lossy conversion, it should be removed as a global instance.
instance instNatCast : NatCast (BitVec w) where
natCast x := BitVec.ofNat w x
/-- Theorem for normalizing the bitvector literal representation. -/
-- TODO: This needs more usage data to assess which direction the simp should go.
@@ -731,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`.

View File

@@ -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]

View File

@@ -745,7 +745,6 @@ theorem le_toNat_of_msb_true {w : Nat} {x : BitVec w} (h : x.msb = true) : 2 ^ (
`x.toInt` is less than `2^(w-1)`.
We phrase the fact in terms of `2^w` to prevent a case split on `w=0` when the lemma is used.
-/
@[grind]
theorem two_mul_toInt_lt {w : Nat} {x : BitVec w} : 2 * x.toInt < 2 ^ w := by
simp only [BitVec.toInt]
rcases w with _|w'
@@ -754,6 +753,8 @@ theorem two_mul_toInt_lt {w : Nat} {x : BitVec w} : 2 * x.toInt < 2 ^ w := by
simp only [Nat.zero_lt_succ, Nat.mul_lt_mul_left, Int.natCast_mul, Int.cast_ofNat_Int]
norm_cast; omega
grind_pattern two_mul_toInt_lt => x.toInt
theorem two_mul_toInt_le {w : Nat} {x : BitVec w} : 2 * x.toInt 2 ^ w - 1 :=
Int.le_sub_one_of_lt two_mul_toInt_lt
@@ -772,7 +773,6 @@ theorem toInt_le {w : Nat} {x : BitVec w} : x.toInt ≤ 2 ^ (w - 1) - 1 :=
`x.toInt` is greater than or equal to `-2^(w-1)`.
We phrase the fact in terms of `2^w` to prevent a case split on `w=0` when the lemma is used.
-/
@[grind]
theorem le_two_mul_toInt {w : Nat} {x : BitVec w} : -2 ^ w 2 * x.toInt := by
simp only [BitVec.toInt]
rcases w with _|w'
@@ -781,6 +781,8 @@ theorem le_two_mul_toInt {w : Nat} {x : BitVec w} : -2 ^ w ≤ 2 * x.toInt := by
simp only [Nat.zero_lt_succ, Nat.mul_lt_mul_left, Int.natCast_mul, Int.cast_ofNat_Int]
norm_cast; omega
grind_pattern le_two_mul_toInt => x.toInt
theorem le_toInt {w : Nat} (x : BitVec w) : -2 ^ (w - 1) x.toInt := by
by_cases h : w = 0
· subst h
@@ -5769,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

View File

@@ -7,11 +7,12 @@ module
prelude
public import Init.Data.Array.Basic
public import Init.Data.Array.DecidableEq
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
@@ -21,6 +22,14 @@ attribute [extern "lean_byte_array_mk"] ByteArray.mk
attribute [extern "lean_byte_array_data"] ByteArray.data
namespace ByteArray
deriving instance BEq for ByteArray
attribute [ext] ByteArray
instance : DecidableEq ByteArray :=
fun _ _ => decidable_of_decidable_of_iff ByteArray.ext_iff.symm
@[extern "lean_mk_empty_byte_array"]
def emptyWithCapacity (c : @& Nat) : ByteArray :=
{ data := #[] }

View File

@@ -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).

View File

@@ -185,7 +185,9 @@ theorem foldrM_loop [Monad m] [LawfulMonad m] (f : Fin (n+1) → α → m α) (x
| zero =>
rw [foldrM_loop_zero, foldrM_loop_succ, pure_bind]
conv => rhs; rw [bind_pure (f 0 x)]
rfl
congr
funext
rw [foldrM_loop_zero]
| succ i ih =>
rw [foldrM_loop_succ, foldrM_loop_succ, bind_assoc]
congr; funext; exact ih ..

View File

@@ -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

View File

@@ -9,6 +9,8 @@ prelude
public import Init.Data.Array.Basic
public import Init.Data.Float
public import Init.Data.Option.Basic
import Init.Ext
public import Init.Data.Array.DecidableEq
public section
universe u
@@ -20,6 +22,11 @@ attribute [extern "lean_float_array_mk"] FloatArray.mk
attribute [extern "lean_float_array_data"] FloatArray.data
namespace FloatArray
deriving instance BEq for FloatArray
attribute [ext] FloatArray
@[extern "lean_mk_empty_float_array"]
def emptyWithCapacity (c : @& Nat) : FloatArray :=
{ data := #[] }

View File

@@ -425,6 +425,10 @@ expectation that the resulting string is valid code.
The `Repr` class is similar, but the expectation is that instances produce valid Lean code.
-/
class ToFormat (α : Type u) where
/--
Converts a value to a `Format` object, with no expectation that the resulting string is valid
code.
-/
format : α Format
export ToFormat (format)

View File

@@ -8,6 +8,7 @@ module
prelude
public import Init.Core
public import Init.Grind.Tactics
public section

View File

@@ -1524,7 +1524,7 @@ private theorem cooper_right_core
have d_pos : (0 : Int) < 1 := by decide
have h₃ : 1 0*x + 0 := Int.one_dvd _
have h := cooper_dvd_right_core a_neg b_pos d_pos h₁ h₂ h₃
simp only [Int.mul_one, gcd_zero, Int.natAbs_of_nonneg (Int.le_of_lt b_pos),
simp only [Int.mul_one, gcd_zero, Int.natAbs_of_nonneg (Int.le_of_lt b_pos),
Int.ediv_self (Int.ne_of_gt b_pos), lcm_one,
Int.zero_mul, Int.mul_zero, Int.add_zero, Int.dvd_zero,
and_true, Int.neg_zero] at h
@@ -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
@@ -1915,6 +1864,11 @@ theorem eq_def (ctx : Context) (x : Var) (xPoly : Poly) (p : Poly)
simp [eq_def_cert]; intro _ h; subst p; simp [h]
rw [ Int.sub_eq_add_neg, Int.sub_self]
theorem eq_def_norm (ctx : Context) (x : Var) (xPoly xPoly' : Poly) (p : Poly)
: eq_def_cert x xPoly' p x.denote ctx = xPoly.denote' ctx xPoly.denote' ctx = xPoly'.denote' ctx p.denote' ctx = 0 := by
simp [eq_def_cert]; intro _ h₁ h₂; subst p; simp [h₁, h₂]
rw [ Int.sub_eq_add_neg, Int.sub_self]
@[expose]
def eq_def'_cert (x : Var) (e : Expr) (p : Poly) : Bool :=
p == .add (-1) x e.norm
@@ -1924,6 +1878,83 @@ theorem eq_def' (ctx : Context) (x : Var) (e : Expr) (p : Poly)
simp [eq_def'_cert]; intro _ h; subst p; simp [h]
rw [ Int.sub_eq_add_neg, Int.sub_self]
@[expose]
def eq_def'_norm_cert (x : Var) (e : Expr) (ePoly ePoly' p : Poly) : Bool :=
ePoly == e.norm && p == .add (-1) x ePoly'
theorem eq_def'_norm (ctx : Context) (x : Var) (e : Expr) (ePoly ePoly' : Poly) (p : Poly)
: eq_def'_norm_cert x e ePoly ePoly' p x.denote ctx = e.denote ctx ePoly.denote' ctx = ePoly'.denote' ctx p.denote' ctx = 0 := by
simp [eq_def'_norm_cert]; intro _ _ h₁ h₂; subst ePoly p; simp [h₁, h₂]
rw [ Int.sub_eq_add_neg, Int.sub_self]
theorem eq_norm_poly (ctx : Context) (p p' : Poly) : p.denote' ctx = p'.denote' ctx p.denote' ctx = 0 p'.denote' ctx = 0 := by
intro h; rw [h]; simp
theorem le_norm_poly (ctx : Context) (p p' : Poly) : p.denote' ctx = p'.denote' ctx p.denote' ctx 0 p'.denote' ctx 0 := by
intro h; rw [h]; simp
theorem diseq_norm_poly (ctx : Context) (p p' : Poly) : p.denote' ctx = p'.denote' ctx p.denote' ctx 0 p'.denote' ctx 0 := by
intro h; rw [h]; simp
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

View File

@@ -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

View File

@@ -98,12 +98,12 @@ instance Attach.instIteratorCollectPartial {α β : Type w} {m : Type w → Type
.defaultImplementation
instance Attach.instIteratorLoop {α β : Type w} {m : Type w Type w'} [Monad m]
[Monad n] {P : β Prop} [Iterator α m β] [MonadLiftT m n] :
{n : Type x Type x'} [Monad n] {P : β Prop} [Iterator α m β] :
IteratorLoop (Attach α m P) m n :=
.defaultImplementation
instance Attach.instIteratorLoopPartial {α β : Type w} {m : Type w Type w'} [Monad m]
[Monad n] {P : β Prop} [Iterator α m β] [MonadLiftT m n] :
{n : Type x Type x'} [Monad n] {P : β Prop} [Iterator α m β] :
IteratorLoopPartial (Attach α m P) m n :=
.defaultImplementation

View File

@@ -231,14 +231,14 @@ instance {α β γ : Type w} {m : Type w → Type w'}
.defaultImplementation
instance FilterMap.instIteratorLoop {α β γ : Type w} {m : Type w Type w'}
{n : Type w Type w''} {o : Type w Type w'''}
{n : Type w Type w''} {o : Type x Type x'}
[Monad n] [Monad o] [Iterator α m β] {lift : α : Type w m α n α}
{f : β PostconditionT n (Option γ)} [Finite α m] :
IteratorLoop (FilterMap α m n lift f) n o :=
.defaultImplementation
instance FilterMap.instIteratorLoopPartial {α β γ : Type w} {m : Type w Type w'}
{n : Type w Type w''} {o : Type w Type w'''}
{n : Type w Type w''} {o : Type x Type x'}
[Monad n] [Monad o] [Iterator α m β] {lift : α : Type w m α n α}
{f : β PostconditionT n (Option γ)} :
IteratorLoopPartial (FilterMap α m n lift f) n o :=
@@ -274,14 +274,14 @@ instance Map.instIteratorCollectPartial {α β γ : Type w} {m : Type w → Type
it.internalState.inner (m := m)
instance Map.instIteratorLoop {α β γ : Type w} {m : Type w Type w'}
{n : Type w Type w''} {o : Type w Type x} [Monad n] [Monad o] [Iterator α m β]
{n : Type w Type w''} {o : Type x Type x'} [Monad n] [Monad o] [Iterator α m β]
{lift : α : Type w m α n α}
{f : β PostconditionT n γ} :
IteratorLoop (Map α m n lift f) n o :=
.defaultImplementation
instance Map.instIteratorLoopPartial {α β γ : Type w} {m : Type w Type w'}
{n : Type w Type w''} {o : Type w Type x} [Monad n] [Monad o] [Iterator α m β]
{n : Type w Type w''} {o : Type x Type x'} [Monad n] [Monad o] [Iterator α m β]
{lift : α : Type w m α n α}
{f : β PostconditionT n γ} :
IteratorLoopPartial (Map α m n lift f) n o :=

View File

@@ -123,15 +123,16 @@ instance Types.ULiftIterator.instProductive [Iterator α m β] [Productive α m]
Productive (ULiftIterator α m n β lift) n :=
.of_productivenessRelation instProductivenessRelation
instance Types.ULiftIterator.instIteratorLoop {o} [Monad n] [Monad o] [Iterator α m β] :
instance Types.ULiftIterator.instIteratorLoop {o : Type x Type x'} [Monad n] [Monad o]
[Iterator α m β] :
IteratorLoop (ULiftIterator α m n β lift) n o :=
.defaultImplementation
instance Types.ULiftIterator.instIteratorLoopPartial {o} [Monad n] [Monad o] [Iterator α m β] :
instance Types.ULiftIterator.instIteratorLoopPartial {o : Type x Type x'} [Monad n] [Monad o] [Iterator α m β] :
IteratorLoopPartial (ULiftIterator α m n β lift) n o :=
.defaultImplementation
instance Types.ULiftIterator.instIteratorCollect {o} [Monad n] [Monad o] [Iterator α m β] :
instance Types.ULiftIterator.instIteratorCollect [Monad n] [Monad o] [Iterator α m β] :
IteratorCollect (ULiftIterator α m n β lift) n o :=
.defaultImplementation

View File

@@ -12,4 +12,6 @@ public import Init.Data.Iterators.Consumers.Collect
public import Init.Data.Iterators.Consumers.Loop
public import Init.Data.Iterators.Consumers.Partial
public import Init.Data.Iterators.Consumers.Stream
public section

View File

@@ -6,12 +6,11 @@ Authors: Paul Reichert
module
prelude
public import Init.Data.Stream
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
@@ -64,15 +63,4 @@ def Iter.atIdx? {α β} [Iterator α Id β] [Productive α Id] [IteratorAccess
| .skip _ => none
| .done => none
instance {α β} [Iterator α Id β] [Productive α Id] [IteratorAccess α Id] :
Stream (Iter (α := α) β) β where
next? it := match (it.toIterM.nextAtIdx? 0).run with
| .yield it' out _ => some (out, it'.toIter)
| .skip _ h => False.elim ?noskip
| .done _ => none
where finally
case noskip =>
revert h
exact IterM.not_isPlausibleNthOutputStep_yield
end Std.Iterators

View File

@@ -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

View File

@@ -33,32 +33,42 @@ so this is not marked as `instance`. This way, more convenient instances can be
or future library improvements will make it more comfortable.
-/
@[always_inline, inline]
def Iter.instForIn' {α : Type w} {β : Type w} {n : Type w Type w'} [Monad n]
def Iter.instForIn' {α : Type w} {β : Type w} {n : Type x Type x'} [Monad n]
[Iterator α Id β] [Finite α Id] [IteratorLoop α Id n] :
ForIn' n (Iter (α := α) β) β fun it out => it.IsPlausibleIndirectOutput out where
forIn' it init f :=
IteratorLoop.finiteForIn' (fun δ (c : Id δ) => pure c.run) |>.forIn' it.toIterM init
IteratorLoop.finiteForIn' (fun _ _ f c => f c.run) |>.forIn' it.toIterM init
fun out h acc =>
f out (Iter.isPlausibleIndirectOutput_iff_isPlausibleIndirectOutput_toIterM.mpr h) acc
instance (α : Type w) (β : Type w) (n : Type w Type w') [Monad n]
instance (α : Type w) (β : Type w) (n : Type x Type x') [Monad n]
[Iterator α Id β] [Finite α Id] [IteratorLoop α Id n] :
ForIn n (Iter (α := α) β) β :=
haveI : ForIn' n (Iter (α := α) β) β _ := Iter.instForIn'
instForInOfForIn'
instance (α : Type w) (β : Type w) (n : Type w Type w') [Monad n]
@[always_inline, inline]
def Iter.Partial.instForIn' {α : Type w} {β : Type w} {n : Type x Type x'} [Monad n]
[Iterator α Id β] [IteratorLoopPartial α Id n] :
ForIn n (Iter.Partial (α := α) β) β where
forIn it init f :=
ForIn.forIn it.it.toIterM.allowNontermination init f
ForIn' n (Iter.Partial (α := α) β) β fun it out => it.it.IsPlausibleIndirectOutput out where
forIn' it init f :=
IteratorLoopPartial.forInPartial (α := α) (m := Id) (n := n) (fun _ _ f c => f c.run)
it.it.toIterM init
fun out h acc =>
f out (Iter.isPlausibleIndirectOutput_iff_isPlausibleIndirectOutput_toIterM.mpr h) acc
instance {m : Type w Type w'}
instance (α : Type w) (β : Type w) (n : Type x Type x') [Monad n]
[Iterator α Id β] [IteratorLoopPartial α Id n] :
ForIn n (Iter.Partial (α := α) β) β :=
haveI : ForIn' n (Iter.Partial (α := α) β) β _ := Iter.Partial.instForIn'
instForInOfForIn'
instance {m : Type x Type x'}
{α : Type w} {β : Type w} [Iterator α Id β] [Finite α Id] [IteratorLoop α Id m] :
ForM m (Iter (α := α) β) β where
forM it f := forIn it PUnit.unit (fun out _ => do f out; return .yield .unit)
instance {m : Type w Type w'}
instance {m : Type x Type x'}
{α : Type w} {β : Type w} [Iterator α Id β] [Finite α Id] [IteratorLoopPartial α Id m] :
ForM m (Iter.Partial (α := α) β) β where
forM it f := forIn it PUnit.unit (fun out _ => do f out; return .yield .unit)
@@ -75,8 +85,8 @@ number of steps. If the iterator is not finite or such an instance is not availa
verify the behavior of the partial variant.
-/
@[always_inline, inline]
def Iter.foldM {m : Type w Type w'} [Monad m]
{α : Type w} {β : Type w} {γ : Type w} [Iterator α Id β] [Finite α Id]
def Iter.foldM {m : Type x Type x'} [Monad m]
{α : Type w} {β : Type w} {γ : Type x} [Iterator α Id β] [Finite α Id]
[IteratorLoop α Id m] (f : γ β m γ)
(init : γ) (it : Iter (α := α) β) : m γ :=
ForIn.forIn it init (fun x acc => ForInStep.yield <$> f acc x)
@@ -91,8 +101,8 @@ This is a partial, potentially nonterminating, function. It is not possible to f
its behavior. If the iterator has a `Finite` instance, consider using `IterM.foldM` instead.
-/
@[always_inline, inline]
def Iter.Partial.foldM {m : Type w Type w'} [Monad m]
{α : Type w} {β : Type w} {γ : Type w} [Iterator α Id β]
def Iter.Partial.foldM {m : Type x Type x'} [Monad m]
{α : Type w} {β : Type w} {γ : Type x} [Iterator α Id β]
[IteratorLoopPartial α Id m] (f : γ β m γ)
(init : γ) (it : Iter.Partial (α := α) β) : m γ :=
ForIn.forIn it init (fun x acc => ForInStep.yield <$> f acc x)
@@ -109,7 +119,7 @@ number of steps. If the iterator is not finite or such an instance is not availa
verify the behavior of the partial variant.
-/
@[always_inline, inline]
def Iter.fold {α : Type w} {β : Type w} {γ : Type w} [Iterator α Id β] [Finite α Id]
def Iter.fold {α : Type w} {β : Type w} {γ : Type x} [Iterator α Id β] [Finite α Id]
[IteratorLoop α Id Id] (f : γ β γ)
(init : γ) (it : Iter (α := α) β) : γ :=
ForIn.forIn (m := Id) it init (fun x acc => ForInStep.yield (f acc x))
@@ -124,7 +134,7 @@ This is a partial, potentially nonterminating, function. It is not possible to f
its behavior. If the iterator has a `Finite` instance, consider using `IterM.fold` instead.
-/
@[always_inline, inline]
def Iter.Partial.fold {α : Type w} {β : Type w} {γ : Type w} [Iterator α Id β]
def Iter.Partial.fold {α : Type w} {β : Type w} {γ : Type x} [Iterator α Id β]
[IteratorLoopPartial α Id Id] (f : γ β γ)
(init : γ) (it : Iter.Partial (α := α) β) : γ :=
ForIn.forIn (m := Id) it init (fun x acc => ForInStep.yield (f acc x))

View File

@@ -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

View File

@@ -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,9 +66,10 @@ 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 w Type w'') where
forIn : (_lift : (γ : Type w) m γ n γ) (γ : Type w),
(n : Type x Type x') where
forIn : (_liftBind : (γ : Type w) (δ : Type x) (γ n δ) m γ n δ) (γ : Type x),
(plausible_forInStep : β γ ForInStep γ Prop)
IteratorLoop.WellFounded α m plausible_forInStep
(it : IterM (α := α) m β) γ
@@ -79,8 +85,8 @@ They can, however, assume that consumers that require an instance will work for
provided by the standard library.
-/
class IteratorLoopPartial (α : Type w) (m : Type w Type w') {β : Type w} [Iterator α m β]
(n : Type w Type w'') where
forInPartial : (_lift : (γ : Type w) m γ n γ) {γ : Type w},
(n : Type x Type x') where
forInPartial : (_liftBind : (γ : Type w) (δ : Type x) (γ n δ) m γ n δ) {γ : Type x},
(it : IterM (α := α) m β) γ
((b : β) it.IsPlausibleIndirectOutput b (c : γ) n (ForInStep γ)) n γ
@@ -108,43 +114,36 @@ 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 w Type w''} [Monad n]
(lift : γ, m γ n γ) (γ : Type w)
{n : Type x Type x'} [Monad n]
(lift : γ δ, (γ n δ) m γ n δ) (γ : Type x)
(plausible_forInStep : β γ ForInStep γ Prop)
(wf : IteratorLoop.WellFounded α m plausible_forInStep)
(it : IterM (α := α) m β) (init : γ)
(P : β Prop) (hP : b, it.IsPlausibleIndirectOutput b P b)
(f : (b : β) P b (c : γ) n (Subtype (plausible_forInStep b c))) : n γ :=
haveI : WellFounded _ := wf
letI : MonadLift m n := fun {γ} => lift γ
do
match it.step with
| .yield it' out h =>
(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
@@ -154,18 +153,50 @@ def IterM.DefaultConsumers.forIn' {m : Type w → Type w'} {α : Type w} {β : T
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
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]
def IteratorLoop.defaultImplementation {α : Type w} {m : Type w Type w'} {n : Type w Type w''}
@[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
forIn lift γ Pl wf it init := IterM.DefaultConsumers.forIn' lift γ Pl wf it init _ (fun _ => id)
@@ -174,9 +205,10 @@ def IteratorLoop.defaultImplementation {α : Type w} {m : Type w → Type w'} {n
Asserts that a given `IteratorLoop` instance is equal to `IteratorLoop.defaultImplementation`.
(Even though equal, the given instance might be vastly more efficient.)
-/
class LawfulIteratorLoop (α : Type w) (m : Type w Type w') (n : Type w Type w'')
[Monad n] [Iterator α m β] [Finite α m] [i : IteratorLoop α m n] where
lawful : i = .defaultImplementation
class LawfulIteratorLoop (α : Type w) (m : Type w Type w') (n : Type x Type x')
[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`.
@@ -184,23 +216,21 @@ This is the loop implementation of the default instance `IteratorLoopPartial.def
@[specialize]
partial def IterM.DefaultConsumers.forInPartial {m : Type w Type w'} {α : Type w} {β : Type w}
[Iterator α m β]
{n : Type w Type w''} [Monad n]
(lift : γ, m γ n γ) (γ : Type w)
{n : Type x Type x'} [Monad n]
(lift : γ δ, (γ n δ) m γ n δ) (γ : Type x)
(it : IterM (α := α) m β) (init : γ)
(f : (b : β) it.IsPlausibleIndirectOutput b (c : γ) n (ForInStep γ)) : n γ :=
letI : MonadLift m n := fun {γ} => lift γ
do
match it.step with
| .yield it' out h =>
match f out (.direct _, h) init with
| .yield c =>
IterM.DefaultConsumers.forInPartial lift _ it' c
(lift _ _ · it.step) fun
| .yield it' out h => do
match f out (.direct _, h) init with
| .yield c =>
IterM.DefaultConsumers.forInPartial lift _ it' c
fun out h' acc => f out (.indirect _, rfl, h h') acc
| .done c => return c
| .skip it' h =>
IterM.DefaultConsumers.forInPartial lift _ it' init
fun out h' acc => f out (.indirect _, rfl, h h') acc
| .done c => return c
| .skip it' h =>
IterM.DefaultConsumers.forInPartial lift _ it' init
fun out h' acc => f out (.indirect _, rfl, h h') acc
| .done _ => return init
| .done _ => return init
/--
This is the default implementation of the `IteratorLoopPartial` class.
@@ -209,19 +239,19 @@ implementations are possible and should be used instead.
-/
@[always_inline, inline]
def IteratorLoopPartial.defaultImplementation {α : Type w} {m : Type w Type w'}
{n : Type w Type w''} [Monad m] [Monad n] [Iterator α m β] :
{n : Type x Type x'} [Monad m] [Monad n] [Iterator α m β] :
IteratorLoopPartial α m n where
forInPartial lift := IterM.DefaultConsumers.forInPartial lift _
instance (α : Type w) (m : Type w Type w') (n : Type w Type w'')
instance (α : Type w) (m : Type w Type w') (n : Type x Type x')
[Monad m] [Monad n] [Iterator α m β] [Finite α m] :
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} [Iterator α m β] [Finite α m] :
{α β : Type w} {γ : Type x} [Iterator α m β] [Finite α m] :
WellFounded α m (γ := γ) fun _ _ _ => True := by
apply Subrelation.wf
(r := InvImage IterM.TerminationMeasures.Finite.Rel (fun p => p.1.finitelyManySteps))
@@ -237,9 +267,9 @@ theorem IteratorLoop.wellFounded_of_finite {m : Type w → Type w'}
This `ForIn'`-style loop construct traverses a finite iterator using an `IteratorLoop` instance.
-/
@[always_inline, inline]
def IteratorLoop.finiteForIn' {m : Type w Type w'} {n : Type w Type w''}
def IteratorLoop.finiteForIn' {m : Type w Type w'} {n : Type x Type x'}
{α : Type w} {β : Type w} [Iterator α m β] [Finite α m] [IteratorLoop α m n]
(lift : γ, m γ n γ) :
(lift : γ δ, (γ n δ) m γ n δ) :
ForIn' n (IterM (α := α) m β) β fun it out => it.IsPlausibleIndirectOutput out where
forIn' {γ} [Monad n] it init f :=
IteratorLoop.forIn (α := α) (m := m) lift γ (fun _ _ _ => True)
@@ -253,23 +283,30 @@ or future library improvements will make it more comfortable.
-/
@[always_inline, inline]
def IterM.instForIn' {m : Type w Type w'} {n : Type w Type w''}
{α : Type w} {β : Type w} [Iterator α m β] [Finite α m] [IteratorLoop α m n]
{α : Type w} {β : Type w} [Iterator α m β] [Finite α m] [IteratorLoop α m n] [Monad n]
[MonadLiftT m n] :
ForIn' n (IterM (α := α) m β) β fun it out => it.IsPlausibleIndirectOutput out :=
IteratorLoop.finiteForIn' (fun _ => monadLift)
IteratorLoop.finiteForIn' (fun _ _ f x => monadLift x >>= f)
instance {m : Type w Type w'} {n : Type w Type w''}
{α : Type w} {β : Type w} [Iterator α m β] [Finite α m] [IteratorLoop α m n]
[MonadLiftT m n] :
[MonadLiftT m n] [Monad n] :
ForIn n (IterM (α := α) m β) β :=
haveI : ForIn' n (IterM (α := α) m β) β _ := IterM.instForIn'
instForInOfForIn'
instance {m : Type w Type w'} {n : Type w Type w''}
{α : Type w} {β : Type w} [Iterator α m β] [IteratorLoopPartial α m n] [MonadLiftT m n] :
@[always_inline, inline]
def IterM.Partial.instForIn' {m : Type w Type w'} {n : Type w Type w''}
{α : Type w} {β : Type w} [Iterator α m β] [IteratorLoopPartial α m n] [MonadLiftT m n] [Monad n] :
ForIn' n (IterM.Partial (α := α) m β) β fun it out => it.it.IsPlausibleIndirectOutput out where
forIn' it init f :=
IteratorLoopPartial.forInPartial (α := α) (m := m) (fun _ => monadLift) it.it init f
forIn' it init f := IteratorLoopPartial.forInPartial (α := α) (m := m) (n := n)
(fun _ _ f x => monadLift x >>= f) it.it init f
instance {m : Type w Type w'} {n : Type w Type w''}
{α : Type w} {β : Type w} [Iterator α m β] [IteratorLoopPartial α m n] [MonadLiftT m n] [Monad n] :
ForIn n (IterM.Partial (α := α) m β) β :=
haveI : ForIn' n (IterM.Partial (α := α) m β) β _ := IterM.Partial.instForIn'
instForInOfForIn'
instance {m : Type w Type w'} {n : Type w Type w''}
{α : Type w} {β : Type w} [Iterator α m β] [Finite α m] [IteratorLoop α m n]

View File

@@ -0,0 +1,27 @@
/-
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Paul Reichert
-/
module
prelude
public import Init.Data.Stream
public import Init.Data.Iterators.Consumers.Access
public section
namespace Std.Iterators
instance {α β} [Iterator α Id β] [Productive α Id] [IteratorAccess α Id] :
Stream (Iter (α := α) β) β where
next? it := match (it.toIterM.nextAtIdx? 0).run with
| .yield it' out _ => some (out, it'.toIter)
| .skip _ h => False.elim ?noskip
| .done _ => none
where finally
case noskip =>
revert h
exact IterM.not_isPlausibleNthOutputStep_yield
end Std.Iterators

View File

@@ -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

View File

@@ -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,27 +17,28 @@ public section
namespace Std.Iterators
theorem Iter.forIn'_eq {α β : Type w} [Iterator α Id β] [Finite α Id]
{m : Type w Type w''} [Monad m] [IteratorLoop α Id m] [hl : LawfulIteratorLoop α Id m]
{γ : Type w} {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 : β) it.IsPlausibleIndirectOutput b γ m (ForInStep γ)} :
letI : ForIn' m (Iter (α := α) β) β _ := Iter.instForIn'
ForIn'.forIn' it init f =
IterM.DefaultConsumers.forIn' (fun _ c => pure c.run) γ (fun _ _ _ => True)
IterM.DefaultConsumers.forIn' (fun _ _ f x => f x.run) γ (fun _ _ _ => True)
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 w Type w''} [Monad m] [IteratorLoop α Id m] [hl : LawfulIteratorLoop α Id m]
{γ : Type w} {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 _ c => pure c.run) γ (fun _ _ _ => True)
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]
@@ -48,7 +50,7 @@ theorem Iter.forIn'_eq_forIn'_toIterM {α β : Type w} [Iterator α Id β]
letI : ForIn' m (IterM (α := α) Id β) β _ := IterM.instForIn'
ForIn'.forIn' it.toIterM init
(fun out h acc => f out (isPlausibleIndirectOutput_iff_isPlausibleIndirectOutput_toIterM.mpr h) acc) := by
rfl
simp [ForIn'.forIn', Iter.instForIn', IterM.instForIn', monadLift]
theorem Iter.forIn_eq_forIn_toIterM {α β : Type w} [Iterator α Id β]
[Finite α Id] {m : Type w Type w''} [Monad m] [LawfulMonad m]
@@ -57,12 +59,12 @@ theorem Iter.forIn_eq_forIn_toIterM {α β : Type w} [Iterator α Id β]
{f : β γ m (ForInStep γ)} :
ForIn.forIn it init f =
ForIn.forIn it.toIterM init f := by
rfl
simp [forIn_eq_forIn', forIn'_eq_forIn'_toIterM, -forIn'_eq_forIn]
theorem Iter.forIn'_eq_match_step {α β : Type w} [Iterator α Id β]
[Finite α Id] {m : Type w Type w''} [Monad m] [LawfulMonad m]
[Finite α Id] {m : Type x Type x''} [Monad m] [LawfulMonad m]
[IteratorLoop α Id m] [LawfulIteratorLoop α Id m]
{γ : Type w} {it : Iter (α := α) β} {init : γ}
{γ : Type x} {it : Iter (α := α) β} {init : γ}
{f : (out : β) _ γ m (ForInStep γ)} :
letI : ForIn' m (Iter (α := α) β) β _ := Iter.instForIn'
ForIn'.forIn' it init f = (do
@@ -77,20 +79,27 @@ theorem Iter.forIn'_eq_match_step {α β : Type w} [Iterator α Id β]
ForIn'.forIn' it' init
fun out h' acc => f out (.indirect _, rfl, h h') acc
| .done _ => return init) := by
rw [Iter.forIn'_eq_forIn'_toIterM, @IterM.forIn'_eq_match_step, Iter.step]
simp only [liftM, monadLift, pure_bind]
generalize it.toIterM.step = step
cases step using PlausibleIterStep.casesOn
· apply bind_congr
simp only [forIn'_eq]
rw [IterM.DefaultConsumers.forIn'_eq_match_step]
simp only [bind_map_left, Iter.step]
cases it.toIterM.step.run using PlausibleIterStep.casesOn
· simp only [IterM.Step.toPure_yield, PlausibleIterStep.yield, toIter_toIterM, toIterM_toIter]
apply bind_congr
intro forInStep
rfl
· rfl
· rfl
cases forInStep
· simp
· simp only
apply IterM.DefaultConsumers.forIn'_eq_forIn'
intros; congr
· simp only
apply IterM.DefaultConsumers.forIn'_eq_forIn'
intros; congr
· simp
theorem Iter.forIn_eq_match_step {α β : Type w} [Iterator α Id β]
[Finite α Id] {m : Type w Type w''} [Monad m] [LawfulMonad m]
[Finite α Id] {m : Type x Type x'} [Monad m] [LawfulMonad m]
[IteratorLoop α Id m] [LawfulIteratorLoop α Id m]
{γ : Type w} {it : Iter (α := α) β} {init : γ}
{γ : Type x} {it : Iter (α := α) β} {init : γ}
{f : β γ m (ForInStep γ)} :
ForIn.forIn it init f = (do
match it.step with
@@ -100,23 +109,15 @@ theorem Iter.forIn_eq_match_step {α β : Type w} [Iterator α Id β]
| .done c => return c
| .skip it' _ => ForIn.forIn it' init f
| .done _ => return init) := by
rw [Iter.forIn_eq_forIn_toIterM, @IterM.forIn_eq_match_step, Iter.step]
simp only [liftM, monadLift, pure_bind]
generalize it.toIterM.step = step
cases step using PlausibleIterStep.casesOn
· apply bind_congr
intro forInStep
rfl
· rfl
· rfl
simp only [forIn_eq_forIn']
exact forIn'_eq_match_step
private theorem Iter.forIn'_toList.aux {ρ : Type u} {α : Type v} {γ : Type w} {m : Type w Type w'}
private theorem Iter.forIn'_toList.aux {ρ : Type u} {α : Type v} {γ : Type x} {m : Type x Type x'}
[Monad m] {_ : Membership α ρ} [ForIn' m ρ α inferInstance]
{r s : ρ} {init : γ} {f : (a : α) _ γ m (ForInStep γ)} (h : r = s) :
forIn' r init f = forIn' s init (fun a h' acc => f a (h h') acc) := by
cases h; rfl
theorem Iter.isPlausibleStep_iff_step_eq {α β} [Iterator α Id β]
[IteratorCollect α Id Id] [Finite α Id]
[LawfulIteratorCollect α Id Id] [LawfulDeterministicIterator α Id]
@@ -185,11 +186,11 @@ theorem Iter.mem_toList_iff_isPlausibleIndirectOutput {α β} [Iterator α Id β
simp [heq, IterStep.successor] at h₁
theorem Iter.forIn'_toList {α β : Type w} [Iterator α Id β]
[Finite α Id] {m : Type w Type w''} [Monad m] [LawfulMonad m]
[Finite α Id] {m : Type x Type x'} [Monad m] [LawfulMonad m]
[IteratorLoop α Id m] [LawfulIteratorLoop α Id m]
[IteratorCollect α Id Id] [LawfulIteratorCollect α Id Id]
[LawfulDeterministicIterator α Id]
{γ : Type w} {it : Iter (α := α) β} {init : γ}
{γ : Type x} {it : Iter (α := α) β} {init : γ}
{f : (out : β) _ γ m (ForInStep γ)} :
letI : ForIn' m (Iter (α := α) β) β _ := Iter.instForIn'
ForIn'.forIn' it.toList init f = ForIn'.forIn' it init (fun out h acc => f out (Iter.mem_toList_iff_isPlausibleIndirectOutput.mpr h) acc) := by
@@ -219,11 +220,11 @@ theorem Iter.forIn'_toList {α β : Type w} [Iterator α Id β]
· simp
theorem Iter.forIn'_eq_forIn'_toList {α β : Type w} [Iterator α Id β]
[Finite α Id] {m : Type w Type w''} [Monad m] [LawfulMonad m]
[Finite α Id] {m : Type x Type x'} [Monad m] [LawfulMonad m]
[IteratorLoop α Id m] [LawfulIteratorLoop α Id m]
[IteratorCollect α Id Id] [LawfulIteratorCollect α Id Id]
[LawfulDeterministicIterator α Id]
{γ : Type w} {it : Iter (α := α) β} {init : γ}
{γ : Type x} {it : Iter (α := α) β} {init : γ}
{f : (out : β) _ γ m (ForInStep γ)} :
letI : ForIn' m (Iter (α := α) β) β _ := Iter.instForIn'
ForIn'.forIn' it init f = ForIn'.forIn' it.toList init (fun out h acc => f out (Iter.mem_toList_iff_isPlausibleIndirectOutput.mp h) acc) := by
@@ -231,10 +232,10 @@ theorem Iter.forIn'_eq_forIn'_toList {α β : Type w} [Iterator α Id β]
congr
theorem Iter.forIn_toList {α β : Type w} [Iterator α Id β]
[Finite α Id] {m : Type w Type w''} [Monad m] [LawfulMonad m]
[Finite α Id] {m : Type x Type x'} [Monad m] [LawfulMonad m]
[IteratorLoop α Id m] [LawfulIteratorLoop α Id m]
[IteratorCollect α Id Id] [LawfulIteratorCollect α Id Id]
{γ : Type w} {it : Iter (α := α) β} {init : γ}
{γ : Type x} {it : Iter (α := α) β} {init : γ}
{f : β γ m (ForInStep γ)} :
ForIn.forIn it.toList init f = ForIn.forIn it init f := by
rw [List.forIn_eq_foldlM]
@@ -250,14 +251,14 @@ theorem Iter.forIn_toList {α β : Type w} [Iterator α Id β]
cases forInStep
· induction it'.toList <;> simp [*]
· simp only [ForIn.forIn] at ihy
simp [ihy h, forIn_eq_forIn_toIterM]
simp [ihy h]
· rename_i it' h
simp only [bind_pure_comp]
rw [ihs h]
· simp
theorem Iter.foldM_eq_forIn {α β γ : Type w} [Iterator α Id β] [Finite α Id] {m : Type w Type w'}
[Monad m] [IteratorLoop α Id m] {f : γ β m γ}
theorem Iter.foldM_eq_forIn {α β : Type w} {γ : Type x} [Iterator α Id β] [Finite α Id]
{m : Type x Type x'} [Monad m] [IteratorLoop α Id m] {f : γ β m γ}
{init : γ} {it : Iter (α := α) β} :
it.foldM (init := init) f = ForIn.forIn it init (fun x acc => ForInStep.yield <$> f acc x) :=
(rfl)
@@ -266,19 +267,19 @@ theorem Iter.foldM_eq_foldM_toIterM {α β : Type w} [Iterator α Id β]
[Finite α Id] {m : Type w Type w''} [Monad m] [LawfulMonad m]
[IteratorLoop α Id m] [LawfulIteratorLoop α Id m]
{γ : Type w} {it : Iter (α := α) β} {init : γ} {f : γ β m γ} :
it.foldM (init := init) f = it.toIterM.foldM (init := init) f :=
(rfl)
it.foldM (init := init) f = it.toIterM.foldM (init := init) f := by
simp [foldM_eq_forIn, IterM.foldM_eq_forIn, forIn_eq_forIn_toIterM]
theorem Iter.forIn_yield_eq_foldM {α β γ δ : Type w} [Iterator α Id β]
[Finite α Id] {m : Type w Type w''} [Monad m] [LawfulMonad m] [IteratorLoop α Id m]
theorem Iter.forIn_yield_eq_foldM {α β : Type w} {γ : Type x} {δ : Type x} [Iterator α Id β]
[Finite α Id] {m : Type x Type x'} [Monad m] [LawfulMonad m] [IteratorLoop α Id m]
[LawfulIteratorLoop α Id m] {f : β γ m δ} {g : β γ δ γ} {init : γ}
{it : Iter (α := α) β} :
ForIn.forIn it init (fun c b => (fun d => .yield (g c b d)) <$> f c b) =
it.foldM (fun b c => g c b <$> f c b) init := by
ForIn.forIn (m := m) it init (fun c b => (fun d => .yield (g c b d)) <$> f c b) =
it.foldM (m := m) (fun b c => g c b <$> f c b) init := by
simp [Iter.foldM_eq_forIn]
theorem Iter.foldM_eq_match_step {α β γ : Type w} [Iterator α Id β] [Finite α Id]
{m : Type w Type w'} [Monad m] [LawfulMonad m] [IteratorLoop α Id m]
theorem Iter.foldM_eq_match_step {α β : Type w} {γ : Type x} [Iterator α Id β] [Finite α Id]
{m : Type x Type x'} [Monad m] [LawfulMonad m] [IteratorLoop α Id m]
[LawfulIteratorLoop α Id m] {f : γ β m γ} {init : γ} {it : Iter (α := α) β} :
it.foldM (init := init) f = (do
match it.step with
@@ -289,20 +290,19 @@ theorem Iter.foldM_eq_match_step {α β γ : Type w} [Iterator α Id β] [Finite
generalize it.step = step
cases step using PlausibleIterStep.casesOn <;> simp [foldM_eq_forIn]
theorem Iter.foldlM_toList {α β γ : Type w} [Iterator α Id β] [Finite α Id] {m : Type w Type w'}
[Monad m] [LawfulMonad m] [IteratorLoop α Id m] [LawfulIteratorLoop α Id m]
[IteratorCollect α Id Id] [LawfulIteratorCollect α Id Id]
{f : γ β m γ}
{init : γ} {it : Iter (α := α) β} :
theorem Iter.foldlM_toList {α β : Type w} {γ : Type x} [Iterator α Id β] [Finite α Id]
{m : Type x Type x'} [Monad m] [LawfulMonad m] [IteratorLoop α Id m]
[LawfulIteratorLoop α Id m] [IteratorCollect α Id Id] [LawfulIteratorCollect α Id Id]
{f : γ β m γ} {init : γ} {it : Iter (α := α) β} :
it.toList.foldlM (init := init) f = it.foldM (init := init) f := by
rw [Iter.foldM_eq_forIn, Iter.forIn_toList]
simp only [List.forIn_yield_eq_foldlM, id_map']
theorem IterM.forIn_eq_foldM {α β : Type w} [Iterator α Id β]
[Finite α Id] {m : Type w Type w''} [Monad m] [LawfulMonad m]
[Finite α Id] {m : Type x Type x'} [Monad m] [LawfulMonad m]
[IteratorLoop α Id m] [LawfulIteratorLoop α Id m]
[IteratorCollect α Id Id] [LawfulIteratorCollect α Id Id]
{γ : Type w} {it : Iter (α := α) β} {init : γ}
{γ : Type x} {it : Iter (α := α) β} {init : γ}
{f : β γ m (ForInStep γ)} :
forIn it init f = ForInStep.value <$>
it.foldM (fun c b => match c with
@@ -310,31 +310,28 @@ theorem IterM.forIn_eq_foldM {α β : Type w} [Iterator α Id β]
| .done c => pure (.done c)) (ForInStep.yield init) := by
simp only [ Iter.forIn_toList, List.forIn_eq_foldlM, Iter.foldlM_toList]; rfl
theorem Iter.fold_eq_forIn {α β γ : Type w} [Iterator α Id β]
theorem Iter.fold_eq_forIn {α β : Type w} {γ : Type x} [Iterator α Id β]
[Finite α Id] [IteratorLoop α Id Id] {f : γ β γ} {init : γ} {it : Iter (α := α) β} :
it.fold (init := init) f =
(ForIn.forIn (m := Id) it init (fun x acc => pure (ForInStep.yield (f acc x)))).run := by
rfl
theorem Iter.fold_eq_foldM {α β γ : Type w} [Iterator α Id β]
[Finite α Id] [IteratorLoop α Id Id] {f : γ β γ} {init : γ}
{it : Iter (α := α) β} :
theorem Iter.fold_eq_foldM {α β : Type w} {γ : Type x} [Iterator α Id β]
[Finite α Id] [IteratorLoop α Id Id] {f : γ β γ} {init : γ} {it : Iter (α := α) β} :
it.fold (init := init) f = (it.foldM (m := Id) (init := init) (pure <| f · ·)).run := by
simp [foldM_eq_forIn, fold_eq_forIn]
@[simp]
theorem Iter.forIn_pure_yield_eq_fold {α β γ : Type w} [Iterator α Id β]
[Finite α Id] [IteratorLoop α Id Id]
[LawfulIteratorLoop α Id Id] {f : β γ γ} {init : γ}
theorem Iter.forIn_pure_yield_eq_fold {α β : Type w} {γ : Type x} [Iterator α Id β]
[Finite α Id] [IteratorLoop α Id Id] [LawfulIteratorLoop α Id Id] {f : β γ γ} {init : γ}
{it : Iter (α := α) β} :
ForIn.forIn (m := Id) it init (fun c b => pure (.yield (f c b))) =
pure (it.fold (fun b c => f c b) init) := by
simp only [fold_eq_forIn]
rfl
theorem Iter.fold_eq_match_step {α β γ : Type w} [Iterator α Id β] [Finite α Id]
[IteratorLoop α Id Id] [LawfulIteratorLoop α Id Id]
{f : γ β γ} {init : γ} {it : Iter (α := α) β} :
theorem Iter.fold_eq_match_step {α β : Type w} {γ : Type x} [Iterator α Id β] [Finite α Id]
[IteratorLoop α Id Id] [LawfulIteratorLoop α Id Id] {f : γ β γ} {init : γ} {it : Iter (α := α) β} :
it.fold (init := init) f = (match it.step with
| .yield it' out _ => it'.fold (init := f init out) f
| .skip it' _ => it'.fold (init := init) f
@@ -345,7 +342,7 @@ theorem Iter.fold_eq_match_step {α β γ : Type w} [Iterator α Id β] [Finite
cases step using PlausibleIterStep.casesOn <;> simp
@[simp]
theorem Iter.foldl_toList {α β γ : Type w} [Iterator α Id β] [Finite α Id]
theorem Iter.foldl_toList {α β : Type w} {γ : Type x} [Iterator α Id β] [Finite α Id]
[IteratorLoop α Id Id] [LawfulIteratorLoop α Id Id]
[IteratorCollect α Id Id] [LawfulIteratorCollect α Id Id]
{f : γ β γ} {init : γ} {it : Iter (α := α) β} :

View File

@@ -15,84 +15,54 @@ namespace Std.Iterators
theorem IterM.DefaultConsumers.forIn'_eq_match_step {α β : Type w} {m : Type w Type w'}
[Iterator α m β]
{n : Type w Type w''} [Monad n]
{lift : γ, m γ n γ} {γ : Type w}
{n : Type x Type x'} [Monad n]
{lift : γ δ, (γ n δ) m γ n δ} {γ : Type x}
{plausible_forInStep : β γ ForInStep γ Prop}
{wf : IteratorLoop.WellFounded α m plausible_forInStep}
{it : IterM (α := α) m β} {init : γ}
{P hP}
{f : (b : β) P b (c : γ) n (Subtype (plausible_forInStep b c))} :
IterM.DefaultConsumers.forIn' lift γ plausible_forInStep wf it init P hP f = (do
match lift _ it.step with
| .yield it' out h =>
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) := by
{P hP} {f : (b : β) P b (c : γ) n (Subtype (plausible_forInStep b c))} :
IterM.DefaultConsumers.forIn' lift γ plausible_forInStep wf it init P hP f =
(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) := by
rw [forIn']
apply bind_congr
intro step
congr; ext step
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' (fun _ => monadLift) γ (fun _ _ _ => True)
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' (fun _ => monadLift) γ (fun _ _ _ => True)
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 w Type w''} [Monad n]
{lift : γ, m γ n γ} {γ : Type w}
{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']
apply bind_congr
intro 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
@@ -125,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
@@ -138,11 +108,10 @@ theorem IterM.forIn_eq_match_step {α β : Type w} {m : Type w → Type w'} [Ite
| .skip it' _ => ForIn.forIn it' init f
| .done _ => return init) := by
simp only [forIn]
rw [forIn'_eq_match_step]
rfl
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} :
@@ -150,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
@@ -173,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) =
@@ -181,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

View File

@@ -6,7 +6,8 @@ Authors: Paul Reichert
module
prelude
public import Init.Data.Iterators.Consumers
public import Init.Data.Iterators.Consumers.Collect
public import Init.Data.Iterators.Consumers.Loop
public section

View File

@@ -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:

View File

@@ -130,7 +130,7 @@ Safer alternatives include:
* `List.head?`, which returns an `Option`, and
* `List.headD`, which returns an explicitly-provided fallback value on empty lists.
-/
def head! [Inhabited α] : List α α
@[expose] def head! [Inhabited α] : List α α
| [] => panic! "empty list"
| a::_ => a
@@ -362,12 +362,13 @@ theorem not_lex_antisymm [DecidableEq α] {r : αα → Prop} [DecidableRel
· exact h₁ (Lex.rel hba)
· exact eq (antisymm _ _ hab hba)
protected theorem le_antisymm [DecidableEq α] [LT α] [DecidableLT α]
protected theorem le_antisymm [LT α]
[i : Std.Antisymm (¬ · < · : α α Prop)]
{as bs : List α} (h₁ : as bs) (h₂ : bs as) : as = bs :=
open Classical in
not_lex_antisymm i.antisymm h₁ h₂
instance [DecidableEq α] [LT α] [DecidableLT α]
instance [LT α]
[s : Std.Antisymm (¬ · < · : α α Prop)] :
Std.Antisymm (· · : List α List α Prop) where
antisymm _ _ h₁ h₂ := List.le_antisymm h₁ h₂

View File

@@ -104,7 +104,6 @@ theorem countP_replicate {p : α → Bool} {a : α} {n : Nat} :
simp only [countP_eq_length_filter, filter_replicate]
split <;> simp
@[grind]
theorem boole_getElem_le_countP {p : α Bool} {l : List α} {i : Nat} (h : i < l.length) :
(if p l[i] then 1 else 0) l.countP p := by
induction l generalizing i with
@@ -118,6 +117,8 @@ theorem boole_getElem_le_countP {p : α → Bool} {l : List α} {i : Nat} (h : i
specialize ih h
exact le_add_right_of_le ih
grind_pattern boole_getElem_le_countP => l.countP p, l[i]
theorem Sublist.countP_le (s : l₁ <+ l₂) : countP p l₁ countP p l₂ := by
simp only [countP_eq_length_filter]
apply s.filter _ |>.length_le
@@ -142,10 +143,11 @@ grind_pattern IsInfix.countP_le => l₁ <:+: l₂, countP p l₂
-- See `Init.Data.List.Nat.Count` for `Sublist.le_countP : countP p l₂ - (l₂.length - l₁.length) ≤ countP p l₁`.
@[grind]
theorem countP_tail_le (l) : countP p l.tail countP p l :=
(tail_sublist l).countP_le
grind_pattern countP_tail_le => countP p l.tail
-- See `Init.Data.List.Nat.Count` for `le_countP_tail : countP p l - 1 ≤ countP p l.tail`.
theorem countP_filter {l : List α} :
@@ -288,12 +290,13 @@ theorem count_flatten {a : α} {l : List (List α)} : count a l.flatten = (l.map
@[simp, grind =] theorem count_reverse {a : α} {l : List α} : count a l.reverse = count a l := by
simp only [count_eq_countP, countP_eq_length_filter, filter_reverse, length_reverse]
@[grind]
theorem boole_getElem_le_count {a : α} {l : List α} {i : Nat} (h : i < l.length) :
(if l[i] == a then 1 else 0) l.count a := by
rw [count_eq_countP]
apply boole_getElem_le_countP (p := (· == a))
grind_pattern boole_getElem_le_count => l.count a, l[i]
variable [LawfulBEq α]
@[simp] theorem count_cons_self {a : α} {l : List α} : count a (a :: l) = count a l + 1 := by

View File

@@ -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

View File

@@ -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]

View File

@@ -13,6 +13,7 @@ public import all Init.Data.List.BasicAux
public import all Init.Data.List.Control
public import Init.Control.Lawful.Basic
public import Init.BinderPredicates
public import Init.GetElemV
public section
@@ -2331,7 +2332,7 @@ theorem filterMap_replicate_of_some {f : α → Option β} (h : f a = some b) :
induction n with
| zero => simp
| succ n ih =>
simp only [replicate_succ, flatten_cons, ih, replicate_append_replicate,
simp only [replicate_succ, flatten_cons, ih, replicate_append_replicate,
add_one_mul, Nat.add_comm]
theorem flatMap_replicate {β} {f : α List β} : (replicate n a).flatMap f = (replicate n (f a)).flatten := by
@@ -3477,13 +3478,15 @@ theorem length_le_length_insert {l : List α} {a : α} : l.length ≤ (l.insert
grind_pattern List.length_le_length_insert => (l.insert a).length
@[grind] theorem length_insert_pos {l : List α} {a : α} : 0 < (l.insert a).length := by
theorem length_insert_pos {l : List α} {a : α} : 0 < (l.insert a).length := by
by_cases h : a l
· rw [length_insert_of_mem h]
exact length_pos_of_mem h
· rw [length_insert_of_not_mem h]
exact Nat.zero_lt_succ _
grind_pattern length_insert_pos => (l.insert a).length
theorem insert_eq {l : List α} {a : α} : l.insert a = if a l then l else a :: l := by
simp [List.insert]
@@ -3727,6 +3730,20 @@ set_option linter.deprecated false in
theorem mem_iff_get? {a} {l : List α} : a l n, l.get? n = some a := by
simp [getElem?_eq_some_iff, Fin.exists_iff, mem_iff_get]
/-! ### `getElemV` -/
noncomputable instance : GetElemV (List α) Nat α where
getElemV xs i := if h : i < xs.length then xs[i] else Classical.arbitrary α
instance : LawfulGetElemV (List α) Nat α (fun xs i => i < xs.length) where
getElemV_def xs i := by
simp [getElemV]
split <;> simp_all
theorem getElemV_map [Nonempty α] [Nonempty β] {xs : List α} {f : α β} (h : i < xs.length) :
(xs.map f)[i] = f xs[i] := by
simp_all [LawfulGetElemV.getElemV_def]
/-! ### Deprecations -/
@[deprecated _root_.isSome_getElem? (since := "2024-12-09")]

View File

@@ -22,9 +22,9 @@ namespace List
@[simp] theorem not_lex_lt [LT α] {l₁ l₂ : List α} : ¬ Lex (· < ·) l₁ l₂ l₂ l₁ := Iff.rfl
protected theorem not_lt_iff_ge [LT α] {l₁ l₂ : List α} : ¬ l₁ < l₂ l₂ l₁ := Iff.rfl
protected theorem not_le_iff_gt [DecidableEq α] [LT α] [DecidableLT α] {l₁ l₂ : List α} :
protected theorem not_le_iff_gt [LT α] {l₁ l₂ : List α} :
¬ l₁ l₂ l₂ < l₁ :=
Decidable.not_not
Classical.not_not
theorem lex_irrefl {r : α α Prop} (irrefl : x, ¬r x x) (l : List α) : ¬Lex r l l := by
induction l with
@@ -78,13 +78,14 @@ theorem not_cons_lex_cons_iff [DecidableEq α] [DecidableRel r] {a b} {l₁ l₂
¬ Lex r (a :: l₁) (b :: l₂) (¬ r a b a b) (¬ r a b ¬ Lex r l₁ l₂) := by
rw [cons_lex_cons_iff, not_or, Decidable.not_and_iff_or_not, and_or_left]
theorem cons_le_cons_iff [DecidableEq α] [LT α] [DecidableLT α]
theorem cons_le_cons_iff [LT α]
[i₀ : Std.Irrefl (· < · : α α Prop)]
[i₁ : Std.Asymm (· < · : α α Prop)]
[i₂ : Std.Antisymm (¬ · < · : α α Prop)]
{a b} {l₁ l₂ : List α} :
(a :: l₁) (b :: l₂) a < b a = b l₁ l₂ := by
dsimp only [instLE, instLT, List.le, List.lt]
open Classical in
simp only [not_cons_lex_cons_iff, ne_eq]
constructor
· rintro (h₁, h₂ | h₁, h₂)
@@ -104,7 +105,7 @@ theorem cons_le_cons_iff [DecidableEq α] [LT α] [DecidableLT α]
· right
exact fun w => i₀.irrefl _ (h₁ w), h₂
theorem not_lt_of_cons_le_cons [DecidableEq α] [LT α] [DecidableLT α]
theorem not_lt_of_cons_le_cons [LT α]
[i₀ : Std.Irrefl (· < · : α α Prop)]
[i₁ : Std.Asymm (· < · : α α Prop)]
[i₂ : Std.Antisymm (¬ · < · : α α Prop)]
@@ -114,7 +115,7 @@ theorem not_lt_of_cons_le_cons [DecidableEq α] [LT α] [DecidableLT α]
· exact i₁.asymm _ _ h
· exact i₀.irrefl _
theorem le_of_cons_le_cons [DecidableEq α] [LT α] [DecidableLT α]
theorem le_of_cons_le_cons [LT α]
[i₀ : Std.Irrefl (· < · : α α Prop)]
[i₁ : Std.Asymm (· < · : α α Prop)]
[i₂ : Std.Antisymm (¬ · < · : α α Prop)]
@@ -165,7 +166,7 @@ instance [LT α] [Trans (· < · : αα → Prop) (· < ·) (· < ·)] :
@[deprecated List.le_antisymm (since := "2024-12-13")]
protected abbrev lt_antisymm := @List.le_antisymm
protected theorem lt_of_le_of_lt [DecidableEq α] [LT α] [DecidableLT α]
protected theorem lt_of_le_of_lt [LT α]
[i₀ : Std.Irrefl (· < · : α α Prop)]
[i₁ : Std.Asymm (· < · : α α Prop)]
[i₂ : Std.Antisymm (¬ · < · : α α Prop)]
@@ -180,7 +181,7 @@ protected theorem lt_of_le_of_lt [DecidableEq α] [LT α] [DecidableLT α]
| cons c l₁ =>
apply Lex.rel
replace h₁ := not_lt_of_cons_le_cons h₁
apply Decidable.byContradiction
apply Classical.byContradiction
intro h₂
have := i₃.trans h₁ h₂
contradiction
@@ -193,9 +194,9 @@ protected theorem lt_of_le_of_lt [DecidableEq α] [LT α] [DecidableLT α]
by_cases w₅ : a = c
· subst w₅
exact Lex.cons (ih (le_of_cons_le_cons h₁))
· exact Lex.rel (Decidable.byContradiction fun w₆ => w₅ (i₂.antisymm _ _ w₄ w₆))
· exact Lex.rel (Classical.byContradiction fun w₆ => w₅ (i₂.antisymm _ _ w₄ w₆))
protected theorem le_trans [DecidableEq α] [LT α] [DecidableLT α]
protected theorem le_trans [LT α]
[Std.Irrefl (· < · : α α Prop)]
[Std.Asymm (· < · : α α Prop)]
[Std.Antisymm (¬ · < · : α α Prop)]
@@ -203,7 +204,7 @@ protected theorem le_trans [DecidableEq α] [LT α] [DecidableLT α]
{l₁ l₂ l₃ : List α} (h₁ : l₁ l₂) (h₂ : l₂ l₃) : l₁ l₃ :=
fun h₃ => h₁ (List.lt_of_le_of_lt h₂ h₃)
instance [DecidableEq α] [LT α] [DecidableLT α]
instance [LT α]
[Std.Irrefl (· < · : α α Prop)]
[Std.Asymm (· < · : α α Prop)]
[Std.Antisymm (¬ · < · : α α Prop)]
@@ -231,9 +232,9 @@ instance [LT α] [Std.Asymm (· < · : αα → Prop)] :
Std.Asymm (· < · : List α List α Prop) where
asymm _ _ := List.lt_asymm
theorem not_lex_total [DecidableEq α] {r : α α Prop} [DecidableRel r]
theorem not_lex_total {r : α α Prop}
(h : x y : α, ¬ r x y ¬ r y x) (l₁ l₂ : List α) : ¬ Lex r l₁ l₂ ¬ Lex r l₂ l₁ := by
rw [Decidable.or_iff_not_imp_left, Decidable.not_not]
rw [Classical.or_iff_not_imp_left, Classical.not_not]
intro w₁ w₂
match l₁, l₂, w₁, w₂ with
| nil, _ :: _, .nil, w₂ => simp at w₂
@@ -246,11 +247,11 @@ theorem not_lex_total [DecidableEq α] {r : αα → Prop} [DecidableRel r]
| _ :: l₁, _ :: l₂, .cons _, .cons _ =>
obtain (_ | _) := not_lex_total h l₁ l₂ <;> contradiction
protected theorem le_total [DecidableEq α] [LT α] [DecidableLT α]
protected theorem le_total [LT α]
[i : Std.Total (¬ · < · : α α Prop)] (l₁ l₂ : List α) : l₁ l₂ l₂ l₁ :=
not_lex_total i.total l₂ l₁
instance [DecidableEq α] [LT α] [DecidableLT α]
instance [LT α]
[Std.Total (¬ · < · : α α Prop)] :
Std.Total (· · : List α List α Prop) where
total := List.le_total
@@ -258,10 +259,10 @@ instance [DecidableEq α] [LT α] [DecidableLT α]
@[simp] protected theorem not_lt [LT α]
{l₁ l₂ : List α} : ¬ l₁ < l₂ l₂ l₁ := Iff.rfl
@[simp] protected theorem not_le [DecidableEq α] [LT α] [DecidableLT α]
{l₁ l₂ : List α} : ¬ l₂ l₁ l₁ < l₂ := Decidable.not_not
@[simp] protected theorem not_le [LT α]
{l₁ l₂ : List α} : ¬ l₂ l₁ l₁ < l₂ := Classical.not_not
protected theorem le_of_lt [DecidableEq α] [LT α] [DecidableLT α]
protected theorem le_of_lt [LT α]
[i : Std.Total (¬ · < · : α α Prop)]
{l₁ l₂ : List α} (h : l₁ < l₂) : l₁ l₂ := by
obtain (h' | h') := List.le_total l₁ l₂
@@ -269,7 +270,7 @@ protected theorem le_of_lt [DecidableEq α] [LT α] [DecidableLT α]
· exfalso
exact h' h
protected theorem le_iff_lt_or_eq [DecidableEq α] [LT α] [DecidableLT α]
protected theorem le_iff_lt_or_eq [LT α]
[Std.Irrefl (· < · : α α Prop)]
[Std.Antisymm (¬ · < · : α α Prop)]
[Std.Total (¬ · < · : α α Prop)]
@@ -280,7 +281,7 @@ protected theorem le_iff_lt_or_eq [DecidableEq α] [LT α] [DecidableLT α]
· right
apply List.le_antisymm h h'
· left
exact Decidable.not_not.mp h'
exact Classical.not_not.mp h'
· rintro (h | rfl)
· exact List.le_of_lt h
· exact List.le_refl l₁
@@ -445,16 +446,17 @@ theorem lex_eq_false_iff_exists [BEq α] [PartialEquivBEq α] (lt : αα
simpa using w₁ (j + 1) (by simpa)
· simpa using w₂
protected theorem lt_iff_exists [DecidableEq α] [LT α] [DecidableLT α] {l₁ l₂ : List α} :
protected theorem lt_iff_exists [LT α] {l₁ l₂ : List α} :
l₁ < l₂
(l₁ = l₂.take l₁.length l₁.length < l₂.length)
( (i : Nat) (h₁ : i < l₁.length) (h₂ : i < l₂.length),
( j, (hj : j < i)
l₁[j]'(Nat.lt_trans hj h₁) = l₂[j]'(Nat.lt_trans hj h₂)) l₁[i] < l₂[i]) := by
open Classical in
rw [ lex_eq_true_iff_lt, lex_eq_true_iff_exists]
simp
protected theorem le_iff_exists [DecidableEq α] [LT α] [DecidableLT α]
protected theorem le_iff_exists [LT α]
[Std.Irrefl (· < · : α α Prop)]
[Std.Asymm (· < · : α α Prop)]
[Std.Antisymm (¬ · < · : α α Prop)] {l₁ l₂ : List α} :
@@ -463,6 +465,7 @@ protected theorem le_iff_exists [DecidableEq α] [LT α] [DecidableLT α]
( (i : Nat) (h₁ : i < l₁.length) (h₂ : i < l₂.length),
( j, (hj : j < i)
l₁[j]'(Nat.lt_trans hj h₁) = l₂[j]'(Nat.lt_trans hj h₂)) l₁[i] < l₂[i]) := by
open Classical in
rw [ lex_eq_false_iff_ge, lex_eq_false_iff_exists]
· simp only [isEqv_eq, beq_iff_eq, decide_eq_true_eq]
simp only [eq_comm]
@@ -477,7 +480,7 @@ theorem append_left_lt [LT α] {l₁ l₂ l₃ : List α} (h : l₂ < l₃) :
| nil => simp [h]
| cons a l₁ ih => simp [cons_lt_cons_iff, ih]
theorem append_left_le [DecidableEq α] [LT α] [DecidableLT α]
theorem append_left_le [LT α]
[Std.Irrefl (· < · : α α Prop)]
[Std.Asymm (· < · : α α Prop)]
[Std.Antisymm (¬ · < · : α α Prop)]
@@ -511,7 +514,7 @@ protected theorem map_lt [LT α] [LT β]
| cons a l₁, cons b l₂, .rel h =>
simp [cons_lt_cons_iff, w, h]
protected theorem map_le [DecidableEq α] [LT α] [DecidableLT α] [DecidableEq β] [LT β] [DecidableLT β]
protected theorem map_le [LT α] [LT β]
[Std.Irrefl (· < · : α α Prop)]
[Std.Asymm (· < · : α α Prop)]
[Std.Antisymm (¬ · < · : α α Prop)]

View File

@@ -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 α} :

View File

@@ -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

View File

@@ -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]

View File

@@ -7,6 +7,7 @@ module
prelude
public import Init.Control.Basic
public import Init.Grind.Tactics
public section
@@ -258,6 +259,55 @@ instance (r : α → β → Prop) [s : DecidableRel r] : DecidableRel (Option.lt
| some _, none => isFalse not_false
| none, none => isFalse not_false
namespace SomeLtNone
/--
Lifts an ordering relation to `Option` such that `none` is the *greatest* element.
It can be understood as adding a distinguished greatest element, represented by `none`, to both `α`
and `β`.
Caution: Given `LT α`, `Option.SomeLtNone.lt LT.lt` differs from the `LT (Option α)` instance,
which is implemented by `Option.lt Lt.lt`.
Examples:
* `Option.lt (fun n k : Nat => n < k) none none = False`
* `Option.lt (fun n k : Nat => n < k) none (some 3) = False`
* `Option.lt (fun n k : Nat => n < k) (some 3) none = True`
* `Option.lt (fun n k : Nat => n < k) (some 4) (some 5) = True`
* `Option.le (fun n k : Nat => n < k) (some 5) (some 4) = False`
* `Option.lt (fun n k : Nat => n < k) (some 4) (some 4) = False`
-/
def lt {α} (r : α β Prop) : Option α Option β Prop
| none, _ => False
| some _, none => True
| some x, some y => r x y
/--
Lifts an ordering relation to `Option` such that `none` is the *greatest* element.
It can be understood as adding a distinguished greatest element, represented by `none`, to both `α`
and `β`.
Caution: Given `LE α`, `Option.SomeLtNone.le LE.le` differs from the `LE (Option α)` instance,
which is implemented by `Option.le LE.le`.
Examples:
* `Option.le (fun n k : Nat => n < k) none none = True`
* `Option.le (fun n k : Nat => n < k) none (some 3) = False`
* `Option.le (fun n k : Nat => n < k) (some 3) none = True`
* `Option.le (fun n k : Nat => n < k) (some 4) (some 5) = True`
* `Option.le (fun n k : Nat => n < k) (some 5) (some 4) = False`
* `Option.le (fun n k : Nat => n < k) (some 4) (some 4) = True`
-/
def le {α} (r : α β Prop) : Option α Option β Prop
| none, none => True
| none, some _ => False
| some _, none => True
| some x, some y => r x y
end SomeLtNone
/--
Applies a function to a two optional values if both are present. Otherwise, if one value is present,
it is returned and the function is not used.

View File

@@ -11,6 +11,7 @@ public import all Init.Data.Option.Instances
public import Init.Data.BEq
public import Init.Classical
public import Init.Ext
public import Init.Grind.Tactics
public section
@@ -1537,15 +1538,22 @@ theorem pfilter_guard {a : α} {p : α → Bool} {q : (a' : α) → guard p a =
/-! ### LT and LE -/
@[simp, grind] theorem not_lt_none [LT α] {a : Option α} : ¬ a < none := by cases a <;> simp [LT.lt, Option.lt]
@[grind] theorem none_lt_some [LT α] {a : α} : none < some a := by simp [LT.lt, Option.lt]
@[simp] theorem not_lt_none [LT α] {a : Option α} : ¬ a < none := by cases a <;> simp [LT.lt, Option.lt]
theorem none_lt_some [LT α] {a : α} : none < some a := by simp [LT.lt, Option.lt]
@[simp] theorem none_lt [LT α] {a : Option α} : none < a a.isSome := by cases a <;> simp [none_lt_some]
@[simp, grind] theorem some_lt_some [LT α] {a b : α} : some a < some b a < b := by simp [LT.lt, Option.lt]
@[simp] theorem some_lt_some [LT α] {a b : α} : some a < some b a < b := by simp [LT.lt, Option.lt]
@[simp, grind] theorem none_le [LE α] {a : Option α} : none a := by cases a <;> simp [LE.le, Option.le]
@[grind] theorem not_some_le_none [LE α] {a : α} : ¬ some a none := by simp [LE.le, Option.le]
@[simp] theorem none_le [LE α] {a : Option α} : none a := by cases a <;> simp [LE.le, Option.le]
theorem not_some_le_none [LE α] {a : α} : ¬ some a none := by simp [LE.le, Option.le]
@[simp] theorem le_none [LE α] {a : Option α} : a none a = none := by cases a <;> simp [not_some_le_none]
@[simp, grind] theorem some_le_some [LE α] {a b : α} : some a some b a b := by simp [LE.le, Option.le]
@[simp] theorem some_le_some [LE α] {a b : α} : some a some b a b := by simp [LE.le, Option.le]
grind_pattern not_lt_none => a < none
grind_pattern none_lt_some => none < some a
grind_pattern some_lt_some => some a < some b
grind_pattern none_le => none a
grind_pattern not_some_le_none => some a none
grind_pattern some_le_some => some a some b
@[simp]
theorem filter_le [LE α] (le_refl : x : α, x x) {o : Option α} {p : α Bool} : o.filter p o := by
@@ -1922,4 +1930,38 @@ theorem map_min [Min α] [Min β] {o o' : Option α} {f : α → β} (hf : ∀ x
(min o o').map f = min (o.map f) (o'.map f) := by
cases o <;> cases o' <;> simp [*]
theorem wellFounded_lt {α} {rel : α α Prop} (h : WellFounded rel) :
WellFounded (Option.lt rel) := by
refine fun x => ?_
have hn : Acc (Option.lt rel) none := by
refine Acc.intro none ?_
intro y hyx
cases y <;> cases hyx
cases x
· exact hn
· rename_i x
induction h.apply x
rename_i _ _ ih
refine Acc.intro _ (fun y hy => ?_)
cases y
· exact hn
· exact ih _ hy
theorem SomeLtNone.wellFounded_lt {α} {r : α α Prop} (h : WellFounded r) :
WellFounded (SomeLtNone.lt r) := by
refine ?_
intro x
constructor
intro x' hlt
match x' with
| none => contradiction
| some x' =>
clear hlt
induction h.apply x'
rename_i ih
refine Acc.intro _ (fun x'' hlt' => ?_)
match x'' with
| none => contradiction
| some x'' => exact ih x'' hlt'
end Option

View File

@@ -247,12 +247,12 @@ theorem isEq_eq_beq_eq : ∀ {o : Ordering}, o.isEq = (o == .eq) := by decide
theorem isNe_eq_not_beq_eq : {o : Ordering}, o.isNe = (!o == .eq) := by decide
theorem isNe_eq_isLT_or_isGT : {o : Ordering}, o.isNe = (o.isLT || o.isGT) := by decide
@[simp] theorem not_isLT_eq_isGE : {o : Ordering}, !o.isLT = o.isGE := by decide
@[simp] theorem not_isLE_eq_isGT : {o : Ordering}, !o.isLE = o.isGT := by decide
@[simp] theorem not_isGT_eq_isLE : {o : Ordering}, !o.isGT = o.isLE := by decide
@[simp] theorem not_isGE_eq_isLT : {o : Ordering}, !o.isGE = o.isLT := by decide
@[simp] theorem not_isNe_eq_isEq : {o : Ordering}, !o.isNe = o.isEq := by decide
theorem not_isEq_eq_isNe : {o : Ordering}, !o.isEq = o.isNe := by decide
@[simp] theorem not_isLT_eq_isGE : {o : Ordering}, (!o.isLT) = o.isGE := by decide
@[simp] theorem not_isLE_eq_isGT : {o : Ordering}, (!o.isLE) = o.isGT := by decide
@[simp] theorem not_isGT_eq_isLE : {o : Ordering}, (!o.isGT) = o.isLE := by decide
@[simp] theorem not_isGE_eq_isLT : {o : Ordering}, (!o.isGE) = o.isLT := by decide
@[simp] theorem not_isNe_eq_isEq : {o : Ordering}, (!o.isNe) = o.isEq := by decide
theorem not_isEq_eq_isNe : {o : Ordering}, (!o.isEq) = o.isNe := by decide
theorem ne_lt_iff_isGE : {o : Ordering}, ¬o = .lt o.isGE := by decide
theorem ne_gt_iff_isLE : {o : Ordering}, ¬o = .gt o.isLE := by decide
@@ -303,7 +303,7 @@ In particular, if `x < y` then the result is `Ordering.lt`. If `x = y` then the
`compareOfLessAndBEq` uses `BEq` instead of `DecidableEq`.
-/
@[inline] def compareOfLessAndEq {α} (x y : α) [LT α] [Decidable (x < y)] [DecidableEq α] : Ordering :=
@[inline, expose] def compareOfLessAndEq {α} (x y : α) [LT α] [Decidable (x < y)] [DecidableEq α] : Ordering :=
if x < y then Ordering.lt
else if x = y then Ordering.eq
else Ordering.gt
@@ -329,7 +329,7 @@ by `cmp₂` to break the tie.
To lexicographically combine two `Ordering`s, use `Ordering.then`.
-/
@[inline] def compareLex (cmp₁ cmp₂ : α β Ordering) (a : α) (b : β) : Ordering :=
@[inline, expose] def compareLex (cmp₁ cmp₂ : α β Ordering) (a : α) (b : β) : Ordering :=
(cmp₁ a b).then (cmp₂ a b)
section Lemmas
@@ -457,7 +457,7 @@ Examples:
* `compareOn (· % 3) 5 6 = .gt`
* `compareOn (·.foldl max 0) [1, 2, 3] [3, 2, 1] = .eq`
-/
@[inline] def compareOn [ord : Ord β] (f : α β) (x y : α) : Ordering :=
@[inline, expose] def compareOn [ord : Ord β] (f : α β) (x y : α) : Ordering :=
compare (f x) (f y)
instance : Ord Nat where
@@ -724,7 +724,7 @@ protected theorem compare_eq_compare_toList {α n} [Ord α] {a b : Vector α n}
end Vector
/-- The lexicographic order on pairs. -/
def lexOrd [Ord α] [Ord β] : Ord (α × β) where
@[expose] def lexOrd [Ord α] [Ord β] : Ord (α × β) where
compare := compareLex (compareOn (·.1)) (compareOn (·.2))
/--
@@ -781,7 +781,7 @@ Inverts the order of an `Ord` instance.
The result is an `Ord α` instance that returns `Ordering.lt` when `ord` would return `Ordering.gt`
and that returns `Ordering.gt` when `ord` would return `Ordering.lt`.
-/
protected def opposite (ord : Ord α) : Ord α where
@[expose] protected def opposite (ord : Ord α) : Ord α where
compare x y := ord.compare y x
/--
@@ -792,13 +792,13 @@ In particular, `ord.on f` compares `x` and `y` by comparing `f x` and `f y` acco
The function `compareOn` can be used to perform this comparison without constructing an intermediate
`Ord` instance.
-/
protected def on (_ : Ord β) (f : α β) : Ord α where
@[expose] protected def on (_ : Ord β) (f : α β) : Ord α where
compare := compareOn f
/--
Constructs the lexicographic order on products `α × β` from orders for `α` and `β`.
-/
protected abbrev lex (_ : Ord α) (_ : Ord β) : Ord (α × β) :=
@[expose] protected abbrev lex (_ : Ord α) (_ : Ord β) : Ord (α × β) :=
lexOrd
/--
@@ -811,7 +811,7 @@ The function `compareLex` can be used to perform this comparison without constru
intermediate `Ord` instance. `Ordering.then` can be used to lexicographically combine the results of
comparisons.
-/
protected def lex' (ord₁ ord₂ : Ord α) : Ord α where
@[expose] protected def lex' (ord₁ ord₂ : Ord α) : Ord α where
compare := compareLex ord₁.compare ord₂.compare
end Ord

View File

@@ -8,6 +8,7 @@ module
prelude
public import Init.Data.Range.Polymorphic.Basic
public import Init.Data.Range.Polymorphic.Iterators
public import Init.Data.Range.Polymorphic.Stream
public import Init.Data.Range.Polymorphic.Lemmas
public import Init.Data.Range.Polymorphic.Nat
public import Init.Data.Range.Polymorphic.NatLemmas

View File

@@ -9,9 +9,8 @@ prelude
public import Init.Data.Range.Polymorphic.RangeIterator
public import Init.Data.Range.Polymorphic.Basic
public import Init.Data.Iterators.Combinators.Attach
public import Init.Data.Stream
public section
@[expose] public section
open Std.Iterators
@@ -26,15 +25,11 @@ def Internal.iter {sl su α} [UpwardEnumerable α] [BoundedUpwardEnumerable sl
(r : PRange sl, su α) : Iter (α := RangeIterator su α) α :=
BoundedUpwardEnumerable.init? r.lower, r.upper
instance {sl su α} [UpwardEnumerable α] [BoundedUpwardEnumerable sl α] :
ToStream (PRange sl, su α) (Iter (α := RangeIterator su α) α) where
toStream r := Internal.iter r
/--
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 α)
@@ -63,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 α]
@@ -147,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

View File

@@ -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]

View File

@@ -110,21 +110,11 @@ 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 RepeatIterator.instIteratorLoop {su} [UpwardEnumerable α] [SupportsUpperBound su α]
{n : Type u Type w} [Monad n] :
IteratorLoop (RangeIterator su α) Id n :=
.defaultImplementation
instance RepeatIterator.instIteratorLoopPartial {su} [UpwardEnumerable α] [SupportsUpperBound su α]
{n : Type u Type w} [Monad n] : IteratorLoopPartial (RangeIterator su α) Id n :=
.defaultImplementation
instance RepeatIterator.instIteratorCollect {su} [UpwardEnumerable α] [SupportsUpperBound su α]
instance RangeIterator.instIteratorCollect {su} [UpwardEnumerable α] [SupportsUpperBound su α]
{n : Type u Type w} [Monad n] : IteratorCollect (RangeIterator su α) Id n :=
.defaultImplementation
instance RepeatIterator.instIteratorCollectPartial {su} [UpwardEnumerable α] [SupportsUpperBound su α]
instance RangeIterator.instIteratorCollectPartial {su} [UpwardEnumerable α] [SupportsUpperBound su α]
{n : Type u Type w} [Monad n] : IteratorCollectPartial (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

View File

@@ -0,0 +1,22 @@
/-
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Paul Reichert
-/
module
prelude
public import Init.Data.Range.Polymorphic.Iterators
public import Init.Data.Stream
public section
open Std.Iterators
namespace Std.PRange
instance {sl su α} [UpwardEnumerable α] [BoundedUpwardEnumerable sl α] :
ToStream (PRange sl, su α) (Iter (α := RangeIterator su α) α) where
toStream r := Internal.iter r
end Std.PRange

View File

@@ -8,8 +8,11 @@ module
prelude
public import Init.Core
public import Init.Data.Slice.Array.Basic
public import Init.Data.Iterators.Combinators.Attach
public import Init.Data.Iterators.Combinators.FilterMap
import Init.Data.Iterators.Combinators.Attach
import Init.Data.Iterators.Combinators.FilterMap
import Init.Data.Iterators.Combinators.ULift
public import Init.Data.Iterators.Consumers.Collect
public import Init.Data.Iterators.Consumers.Loop
public import all Init.Data.Range.Polymorphic.Basic
public import Init.Data.Range.Polymorphic.Nat
public import Init.Data.Range.Polymorphic.Iterators
@@ -26,6 +29,7 @@ open Std Slice PRange Iterators
variable {shape : RangeShape} {α : Type u}
@[no_expose]
instance {s : Subarray α} : ToIterator s Id α :=
.of _
(PRange.Internal.iter (s.internalRepresentation.start...<s.internalRepresentation.stop)
@@ -39,3 +43,102 @@ where finally
intro out _ h
have := s.internalRepresentation.stop_le_array_size
omega
universe v w
@[no_expose] instance {s : Subarray α} : Iterator (ToIterator.State s Id) Id α := inferInstance
@[no_expose] instance {s : Subarray α} : Finite (ToIterator.State s Id) Id := inferInstance
@[no_expose] instance {s : Subarray α} : IteratorCollect (ToIterator.State s Id) Id Id := inferInstance
@[no_expose] instance {s : Subarray α} : IteratorCollectPartial (ToIterator.State s Id) Id Id := inferInstance
@[no_expose] instance {s : Subarray α} {m : Type v Type w} [Monad m] :
IteratorLoop (ToIterator.State s Id) Id m := inferInstance
@[no_expose] instance {s : Subarray α} {m : Type v Type w} [Monad m] :
IteratorLoopPartial (ToIterator.State s Id) Id m := inferInstance
@[no_expose] instance {s : Subarray α} :
IteratorSize (ToIterator.State s Id) Id := inferInstance
@[no_expose] instance {s : Subarray α} :
IteratorSizePartial (ToIterator.State s Id) Id := inferInstance
@[no_expose]
instance {α : Type u} {m : Type v Type w} :
ForIn m (Subarray α) α where
forIn xs init f := forIn (Std.Slice.Internal.iter xs) init f
/-!
Without defining the following function `Subarray.foldlM`, it is still possible to call
`subarray.foldlM`, which would be elaborated to `Slice.foldlM (s := subarray)`. However, in order to
maximize backward compatibility and avoid confusion in the manual entry for `Subarray`, we
explicitly provide the wrapper function `Subarray.foldlM` for `Slice.foldlM`, providing a more
specific docstring.
-/
/--
Folds a monadic operation from left to right over the elements in a subarray.
An accumulator of type `β` is constructed by starting with `init` and monadically combining each
element of the subarray with the current accumulator value in turn. The monad in question may permit
early termination or repetition.
Examples:
```lean example
#eval #["red", "green", "blue"].toSubarray.foldlM (init := "") fun acc x => do
let l ← Option.guard (· ≠ 0) x.length
return s!"{acc}({l}){x} "
```
```output
some "(3)red (5)green (4)blue "
```
```lean example
#eval #["red", "green", "blue"].toSubarray.foldlM (init := 0) fun acc x => do
let l ← Option.guard (· ≠ 5) x.length
return s!"{acc}({l}){x} "
```
```output
none
```
-/
@[inline]
def 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 α :=
Slice.toArray s
instance : Coe (Subarray α) (Array α) := ofSubarray
instance : Append (Subarray α) where
append x y :=
let a := x.toArray ++ y.toArray
a.toSubarray 0 a.size
/-- `Subarray` representation. -/
protected def Subarray.repr [Repr α] (s : Subarray α) : Std.Format :=
repr s.toArray ++ ".toSubarray"
instance [Repr α] : Repr (Subarray α) where
reprPrec s _ := Subarray.repr s
instance [ToString α] : ToString (Subarray α) where
toString s := toString s.toArray
end Array
@[inherit_doc Array.ofSubarray]
def Subarray.toArray (s : Subarray α) : Array α :=
Array.ofSubarray s

View File

@@ -21,7 +21,7 @@ open Std.Iterators Std.PRange
namespace Std.Slice.Array
theorem internalIter_eq {α : Type u} {s : Subarray α} :
private theorem internalIter_eq {α : Type u} {s : Subarray α} :
Internal.iter s = (PRange.Internal.iter (s.start...<s.stop)
|>.attachWith (· < s.array.size)
(fun out h => h
@@ -32,7 +32,7 @@ theorem internalIter_eq {α : Type u} {s : Subarray α} :
|>.map fun | .up i => s.array[i.1]) := by
simp [Internal.iter, ToIterator.iter_eq, Subarray.start, Subarray.stop, Subarray.array]
theorem toList_internalIter {α : Type u} {s : Subarray α} :
private theorem toList_internalIter {α : Type u} {s : Subarray α} :
(Internal.iter s).toList =
((s.start...s.stop).toList
|>.attachWith (· < s.array.size)

View File

@@ -7,6 +7,7 @@ module
prelude
public import all Init.Data.Slice.Operations
import Init.Data.Iterators.Lemmas.Consumers
public section

View File

@@ -8,7 +8,7 @@ module
prelude
public import Init.Data.Slice.Basic
public import Init.Data.Slice.Notation
public import Init.Data.Iterators
public import Init.Data.Iterators.ToIterator
public section
@@ -34,26 +34,72 @@ Returns the number of elements with distinct indices in the given slice.
Example: `#[1, 1, 1][0...2].size = 2`.
-/
@[always_inline, inline]
def size (s : Slice g) [ToIterator s Id β] [Iterator (ToIterator.State s Id) Id β]
def size (s : Slice γ) [ToIterator s Id β] [Iterator (ToIterator.State s Id) Id β]
[IteratorSize (ToIterator.State s Id) Id] :=
Internal.iter s |>.size
/-- Allocates a new array that contains the elements of the slice. -/
@[always_inline, inline]
def toArray (s : Slice g) [ToIterator s Id β] [Iterator (ToIterator.State s Id) Id β]
def toArray (s : Slice γ) [ToIterator s Id β] [Iterator (ToIterator.State s Id) Id β]
[IteratorCollect (ToIterator.State s Id) Id Id] [Finite (ToIterator.State s Id) Id] : Array β :=
Internal.iter s |>.toArray
/-- Allocates a new list that contains the elements of the slice. -/
@[always_inline, inline]
def toList (s : Slice g) [ToIterator s Id β] [Iterator (ToIterator.State s Id) Id β]
def toList (s : Slice γ) [ToIterator s Id β] [Iterator (ToIterator.State s Id) Id β]
[IteratorCollect (ToIterator.State s Id) Id Id] [Finite (ToIterator.State s Id) Id] : List β :=
Internal.iter s |>.toList
/-- Allocates a new list that contains the elements of the slice in reverse order. -/
@[always_inline, inline]
def toListRev (s : Slice g) [ToIterator s Id β] [Iterator (ToIterator.State s Id) Id β]
def toListRev (s : Slice γ) [ToIterator s Id β] [Iterator (ToIterator.State s Id) Id β]
[Finite (ToIterator.State s Id) Id] : List β :=
Internal.iter s |>.toListRev
/--
Folds a monadic operation from left to right over the elements in a slice.
An accumulator of type `β` is constructed by starting with `init` and monadically combining each
element of the slice with the current accumulator value in turn. The monad in question may permit
early termination or repetition.
Examples for the special case of subarrays:
```lean example
#eval #["red", "green", "blue"].toSubarray.foldlM (init := "") fun acc x => do
let l ← Option.guard (· ≠ 0) x.length
return s!"{acc}({l}){x} "
```
```output
some "(3)red (5)green (4)blue "
```
```lean example
#eval #["red", "green", "blue"].toSubarray.foldlM (init := 0) fun acc x => do
let l ← Option.guard (· ≠ 5) x.length
return s!"{acc}({l}){x} "
```
```output
none
```
-/
@[always_inline, inline]
def foldlM {γ : Type u} {β : Type v}
{δ : Type w} {m : Type w Type w'} [Monad m] (f : δ β m δ) (init : δ)
(s : Slice γ) [ToIterator s Id β] [Iterator (ToIterator.State s Id) Id β]
[IteratorLoop (ToIterator.State s Id) Id m] [Finite (ToIterator.State s Id) Id] : m δ :=
Internal.iter s |>.foldM f init
/--
Folds an operation from left to right over the elements in a slice.
An accumulator of type `β` is constructed by starting with `init` and combining each
element of the slice with the current accumulator value in turn.
Examples for the special case of subarrays:
* `#["red", "green", "blue"].toSubarray.foldl (· + ·.length) 0 = 12`
* `#["red", "green", "blue"].toSubarray.popFront.foldl (· + ·.length) 0 = 9`
-/
@[always_inline, inline]
def foldl {γ : Type u} {β : Type v}
{δ : Type w} (f : δ β δ) (init : δ)
(s : Slice γ) [ToIterator s Id β] [Iterator (ToIterator.State s Id) Id β]
[IteratorLoop (ToIterator.State s Id) Id Id] [Finite (ToIterator.State s Id) Id] : δ :=
Internal.iter s |>.fold f init
end Std.Slice

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -55,11 +55,12 @@ theorem getElem_eraseIdx {xs : Vector α n} {i : Nat} (h : i < n) {j : Nat} (h'
rw [ getElem?_eq_getElem, getElem?_eraseIdx]
split <;> simp
@[grind ]
theorem mem_of_mem_eraseIdx {xs : Vector α n} {i : Nat} {h} {a : α} (h : a xs.eraseIdx i) : a xs := by
rcases xs with xs, rfl
simpa using Array.mem_of_mem_eraseIdx (by simpa using h)
grind_pattern mem_of_mem_eraseIdx => a xs.eraseIdx i
theorem eraseIdx_append_of_lt_size {xs : Vector α n} {k : Nat} (hk : k < n) (xs' : Vector α n) (h) :
eraseIdx (xs ++ xs') k = (eraseIdx xs k ++ xs').cast (by omega) := by
rcases xs with xs

View File

@@ -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
@@ -828,7 +828,7 @@ theorem getElem?_eq_none {xs : Vector α n} (h : n ≤ i) : xs[i]? = none := by
-- This is a more aggressive pattern than for `List/Array.getElem?_eq_none`, because
-- `length/size` won't appear.
grind_pattern Vector.getElem?_eq_none => n i, xs[i]?
grind_pattern Vector.getElem?_eq_none => xs[i]?
@[simp] theorem getElem?_eq_getElem {xs : Vector α n} {i : Nat} (h : i < n) : xs[i]? = some xs[i] :=
getElem?_pos ..
@@ -1213,18 +1213,18 @@ theorem contains_iff [BEq α] [LawfulBEq α] {a : α} {as : Vector α n} :
instance [BEq α] [LawfulBEq α] (a : α) (as : Vector α n) : Decidable (a as) :=
decidable_of_decidable_of_iff contains_iff
@[grind] theorem contains_empty [BEq α] : (#v[] : Vector α 0).contains a = false := rfl
@[grind] theorem contains_empty [BEq α] : (#v[] : Vector α 0).contains a = false := by simp
@[simp, grind] theorem contains_eq_mem [BEq α] [LawfulBEq α] {a : α} {as : Vector α n} :
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
@@ -1287,11 +1287,12 @@ theorem mem_set {xs : Vector α n} {i : Nat} {a : α} (hi : i < n) : a ∈ xs.se
simp [mem_iff_getElem]
exact i, (by simpa using hi), by simp
@[grind ]
theorem mem_or_eq_of_mem_set {xs : Vector α n} {i : Nat} {a b : α} {hi : i < n} (h : a xs.set i b) : a xs a = b := by
cases xs
simpa using Array.mem_or_eq_of_mem_set (by simpa using h)
grind_pattern mem_or_eq_of_mem_set => a xs.set i b
/-! ### setIfInBounds -/
@[simp, grind] theorem setIfInBounds_empty {i : Nat} {a : α} :
@@ -2975,7 +2976,7 @@ variable [BEq α]
rcases xs with xs, rfl
simp
@[simp, grind] theorem replace_empty : (#v[] : Vector α 0).replace a b = #v[] := by rfl
@[simp, grind] theorem replace_empty : (#v[] : Vector α 0).replace a b = #v[] := by simp
@[grind] theorem replace_singleton {a b c : α} : #v[a].replace b c = #v[if a == b then c else a] := by
simp

View File

@@ -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
@@ -21,16 +22,19 @@ namespace Vector
/-! ### Lexicographic ordering -/
@[simp, grind =] theorem lt_toArray [LT α] {xs ys : Vector α n} : xs.toArray < ys.toArray xs < ys := Iff.rfl
@[simp, grind =] theorem le_toArray [LT α] {xs ys : Vector α n} : xs.toArray ys.toArray xs ys := Iff.rfl
@[simp] theorem lt_toArray [LT α] {xs ys : Vector α n} : xs.toArray < ys.toArray xs < ys := Iff.rfl
@[simp] theorem le_toArray [LT α] {xs ys : Vector α n} : xs.toArray ys.toArray xs ys := Iff.rfl
grind_pattern lt_toArray => xs.toArray < ys.toArray
grind_pattern le_toArray => xs.toArray ys.toArray
@[simp] theorem lt_toList [LT α] {xs ys : Vector α n} : xs.toList < ys.toList xs < ys := Iff.rfl
@[simp] theorem le_toList [LT α] {xs ys : Vector α n} : xs.toList ys.toList xs ys := Iff.rfl
protected theorem not_lt_iff_ge [LT α] {xs ys : Vector α n} : ¬ xs < ys ys xs := Iff.rfl
protected theorem not_le_iff_gt [DecidableEq α] [LT α] [DecidableLT α] {xs ys : Vector α n} :
protected theorem not_le_iff_gt [LT α] {xs ys : Vector α n} :
¬ xs ys ys < xs :=
Decidable.not_not
Classical.not_not
@[simp] theorem mk_lt_mk [LT α] :
Vector.mk (α := α) (n := n) data₁ size₁ < Vector.mk data₂ size₂ data₁ < data₂ := Iff.rfl
@@ -40,7 +44,7 @@ protected theorem not_le_iff_gt [DecidableEq α] [LT α] [DecidableLT α] {xs ys
@[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} :
@@ -92,7 +96,7 @@ instance [LT α]
Trans (· < · : Vector α n Vector α n Prop) (· < ·) (· < ·) where
trans h₁ h₂ := Vector.lt_trans h₁ h₂
protected theorem lt_of_le_of_lt [DecidableEq α] [LT α] [DecidableLT α]
protected theorem lt_of_le_of_lt [LT α]
[i₀ : Std.Irrefl (· < · : α α Prop)]
[i₁ : Std.Asymm (· < · : α α Prop)]
[i₂ : Std.Antisymm (¬ · < · : α α Prop)]
@@ -100,7 +104,7 @@ protected theorem lt_of_le_of_lt [DecidableEq α] [LT α] [DecidableLT α]
{xs ys zs : Vector α n} (h₁ : xs ys) (h₂ : ys < zs) : xs < zs :=
Array.lt_of_le_of_lt h₁ h₂
protected theorem le_trans [DecidableEq α] [LT α] [DecidableLT α]
protected theorem le_trans [LT α]
[Std.Irrefl (· < · : α α Prop)]
[Std.Asymm (· < · : α α Prop)]
[Std.Antisymm (¬ · < · : α α Prop)]
@@ -108,7 +112,7 @@ protected theorem le_trans [DecidableEq α] [LT α] [DecidableLT α]
{xs ys zs : Vector α n} (h₁ : xs ys) (h₂ : ys zs) : xs zs :=
fun h₃ => h₁ (Vector.lt_of_le_of_lt h₂ h₃)
instance [DecidableEq α] [LT α] [DecidableLT α]
instance [LT α]
[Std.Irrefl (· < · : α α Prop)]
[Std.Asymm (· < · : α α Prop)]
[Std.Antisymm (¬ · < · : α α Prop)]
@@ -120,16 +124,16 @@ protected theorem lt_asymm [LT α]
[i : Std.Asymm (· < · : α α Prop)]
{xs ys : Vector α n} (h : xs < ys) : ¬ ys < xs := Array.lt_asymm h
instance [DecidableEq α] [LT α] [DecidableLT α]
instance [LT α]
[Std.Asymm (· < · : α α Prop)] :
Std.Asymm (· < · : Vector α n Vector α n Prop) where
asymm _ _ := Vector.lt_asymm
protected theorem le_total [DecidableEq α] [LT α] [DecidableLT α]
protected theorem le_total [LT α]
[i : Std.Total (¬ · < · : α α Prop)] (xs ys : Vector α n) : xs ys ys xs :=
Array.le_total _ _
instance [DecidableEq α] [LT α] [DecidableLT α]
instance [LT α]
[Std.Total (¬ · < · : α α Prop)] :
Std.Total (· · : Vector α n Vector α n Prop) where
total := Vector.le_total
@@ -137,15 +141,15 @@ instance [DecidableEq α] [LT α] [DecidableLT α]
@[simp] protected theorem not_lt [LT α]
{xs ys : Vector α n} : ¬ xs < ys ys xs := Iff.rfl
@[simp] protected theorem not_le [DecidableEq α] [LT α] [DecidableLT α]
{xs ys : Vector α n} : ¬ ys xs xs < ys := Decidable.not_not
@[simp] protected theorem not_le [LT α]
{xs ys : Vector α n} : ¬ ys xs xs < ys := Classical.not_not
protected theorem le_of_lt [DecidableEq α] [LT α] [DecidableLT α]
protected theorem le_of_lt [LT α]
[i : Std.Total (¬ · < · : α α Prop)]
{xs ys : Vector α n} (h : xs < ys) : xs ys :=
Array.le_of_lt h
protected theorem le_iff_lt_or_eq [DecidableEq α] [LT α] [DecidableLT α]
protected theorem le_iff_lt_or_eq [LT α]
[Std.Irrefl (· < · : α α Prop)]
[Std.Antisymm (¬ · < · : α α Prop)]
[Std.Total (¬ · < · : α α Prop)]
@@ -210,14 +214,14 @@ theorem lex_eq_false_iff_exists [BEq α] [PartialEquivBEq α] (lt : αα
rcases ys with ys, n₂
simp_all [Array.lex_eq_false_iff_exists]
protected theorem lt_iff_exists [DecidableEq α] [LT α] [DecidableLT α] {xs ys : Vector α n} :
protected theorem lt_iff_exists [LT α] {xs ys : Vector α n} :
xs < ys
( (i : Nat) (h : i < n), ( j, (hj : j < i) xs[j] = ys[j]) xs[i] < ys[i]) := by
cases xs
cases ys
simp_all [Array.lt_iff_exists]
protected theorem le_iff_exists [DecidableEq α] [LT α] [DecidableLT α]
protected theorem le_iff_exists [LT α]
[Std.Irrefl (· < · : α α Prop)]
[Std.Asymm (· < · : α α Prop)]
[Std.Antisymm (¬ · < · : α α Prop)] {xs ys : Vector α n} :
@@ -232,7 +236,7 @@ theorem append_left_lt [LT α] {xs : Vector α n} {ys ys' : Vector α m} (h : ys
xs ++ ys < xs ++ ys' := by
simpa using Array.append_left_lt h
theorem append_left_le [DecidableEq α] [LT α] [DecidableLT α]
theorem append_left_le [LT α]
[Std.Irrefl (· < · : α α Prop)]
[Std.Asymm (· < · : α α Prop)]
[Std.Antisymm (¬ · < · : α α Prop)]
@@ -245,7 +249,7 @@ protected theorem map_lt [LT α] [LT β]
map f xs < map f ys := by
simpa using Array.map_lt w h
protected theorem map_le [DecidableEq α] [LT α] [DecidableLT α] [DecidableEq β] [LT β] [DecidableLT β]
protected theorem map_le [LT α] [LT β]
[Std.Irrefl (· < · : α α Prop)]
[Std.Asymm (· < · : α α Prop)]
[Std.Antisymm (¬ · < · : α α Prop)]

View File

@@ -362,10 +362,9 @@ instance : GetElem? (List α) Nat α fun as i => i < as.length where
theorem none_eq_getElem?_iff {l : List α} {i : Nat} : none = l[i]? length l i := by
simp [eq_comm (a := none)]
@[grind =]
theorem getElem?_eq_none (h : length l i) : l[i]? = none := getElem?_eq_none_iff.mpr h
grind_pattern List.getElem?_eq_none => l.length i, l[i]?
instance : LawfulGetElem (List α) Nat α fun as i => i < as.length where
getElem?_def as i h := by
split <;> simp_all

48
src/Init/GetElemV.lean Normal file
View File

@@ -0,0 +1,48 @@
/-
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Kim Morrison
-/
module
prelude
public import Init.GetElem
public import Init.Classical
public section
@[inherit_doc GetElem]
class GetElemV (coll : Type u) (idx : Type v) (elem : outParam (Type w)) where
/--
The syntax `arr[i]ᵛ` gets the `i`'th element of the collection `arr`,
if it is present, and otherwise returns a (noncomputable) default value.
-/
getElemV [Nonempty elem] : coll idx elem
export GetElemV (getElemV)
/--
The syntax `arr[i]ᵛ` gets the `i`'th element of the collection `arr` or
a (noncomputable) default value if `i` is out of bounds.
-/
macro:max x:term noWs "[" i:term "]ᵛ" : term => `(getElemV $x $i)
recommended_spelling "getElemV" for "xs[i]ᵛ" in [GetElemV.getElemV, «term__[_]»]
open Classical
noncomputable instance (priority := low) [GetElem coll idx elem valid] : GetElemV coll idx elem where
getElemV xs i := if h : valid xs i then xs[i]'h else choice Nonempty elem
class LawfulGetElemV (cont : Type u) (idx : Type v) (elem : outParam (Type w))
(dom : outParam (cont idx Prop)) [GetElem cont idx elem dom] [GetElemV cont idx elem] : Prop where
/-- The "verification only" getter notation `xs[i]ᵛ` coincides with the usual `xs[i]`. -/
getElemV_def [Nonempty elem] (c : cont) (i : idx) :
c[i] = if h : dom c i then c[i]'h else choice Nonempty elem
theorem getElem_eq_getElemV
[GetElem coll idx elem valid] [GetElemV coll idx elem]
[LawfulGetElemV coll idx elem valid] {xs : coll} {i : idx} (h : valid xs i) :
xs[i] = @GetElemV.getElemV _ _ _ _ xs[i] xs i := by
have : Nonempty elem := xs[i]
rw [LawfulGetElemV.getElemV_def, dif_pos h]

View File

@@ -20,6 +20,7 @@ public import Init.Grind.Ordered
public import Init.Grind.Ext
public import Init.Grind.ToInt
public import Init.Grind.ToIntLemmas
public import Init.Grind.Attr
public import Init.Data.Int.OfNat -- This may not have otherwise been imported, breaking `grind` proofs.
public section

93
src/Init/Grind/Attr.lean Normal file
View File

@@ -0,0 +1,93 @@
/-
Copyright (c) 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
module
prelude
public import Init.Tactics
public section
namespace Lean.Grind
/--
Gadget for representing generalization steps `h : x = val` in patterns
This gadget is used to represent patterns in theorems that have been generalized to reduce the
number of casts introduced during E-matching based instantiation.
For example, consider the theorem
```
Option.pbind_some {α1 : Type u_1} {a : α1} {α2 : Type u_2}
{f : (a_1 : α1) → some a = some a_1 → Option α2}
: (some a).pbind f = f a rfl
```
Now, suppose we have a goal containing the term `c.pbind g` and the equivalence class
`{c, some b}`. The E-matching module generates the instance
```
(some b).pbind (cast ⋯ g)
```
The `cast` is necessary because `g`'s type contains `c` instead of `some b.
This `cast` problematic because we don't have a systematic way of pushing casts over functions
to its arguments. Moreover, heterogeneous equality is not effective because the following theorem
is not provable in DTT:
```
theorem hcongr (h₁ : f ≍ g) (h₂ : a ≍ b) : f a ≍ g b := ...
```
The standard solution is to generalize the theorem above and write it as
```
theorem Option.pbind_some'
{α1 : Type u_1} {a : α1} {α2 : Type u_2}
{x : Option α1}
{f : (a_1 : α1) → x = some a_1 → Option α2}
(h : x = some a)
: x.pbind f = f a h := by
subst h
apply Option.pbind_some
```
Internally, we use this gadget to mark the E-matching pattern as
```
(genPattern h x (some a)).pbind f
```
This pattern is matched in the same way we match `(some a).pbind f`, but it saves the proof
for the actual term to the `some`-application in `f`, and the actual term in `x`.
In the example above, `c.pbind g` also matches the pattern `(genPattern h x (some a)).pbind f`,
and stores `c` in `x`, `b` in `a`, and the proof that `c = some b` in `h`.
-/
def genPattern {α : Sort u} (_h : Prop) (x : α) (_val : α) : α := x
/-- Similar to `genPattern` but for the heterogeneous case -/
def genHEqPattern {α β : Sort u} (_h : Prop) (x : α) (_val : β) : α := x
end Lean.Grind
namespace Lean.Parser
/--
Reset all `grind` attributes. This command is intended for testing purposes only and should not be used in applications.
-/
syntax (name := resetGrindAttrs) "reset_grind_attrs%" : command
namespace Attr
syntax grindGen := ppSpace &"gen"
syntax grindEq := "=" (grindGen)?
syntax grindEqBoth := atomic("_" "=" "_") (grindGen)?
syntax grindEqRhs := atomic("=" "_") (grindGen)?
syntax grindEqBwd := patternIgnore(atomic("" "=") <|> atomic("<-" "="))
syntax grindBwd := patternIgnore("" <|> "<-") (grindGen)?
syntax grindFwd := patternIgnore("" <|> "->")
syntax grindRL := patternIgnore("" <|> "<=")
syntax grindLR := patternIgnore("" <|> "=>")
syntax grindUsr := &"usr"
syntax grindCases := &"cases"
syntax grindCasesEager := atomic(&"cases" &"eager")
syntax grindIntro := &"intro"
syntax grindExt := &"ext"
syntax grindSym := &"symbol" ppSpace prio
syntax grindMod :=
grindEqBoth <|> grindEqRhs <|> grindEq <|> grindEqBwd <|> grindBwd
<|> grindFwd <|> grindRL <|> grindLR <|> grindUsr <|> grindCasesEager
<|> grindCases <|> grindIntro <|> grindExt <|> grindGen <|> grindSym
syntax (name := grind) "grind" (ppSpace grindMod)? : attr
syntax (name := grind?) "grind?" (ppSpace grindMod)? : attr
end Attr
end Lean.Parser

View File

@@ -11,5 +11,5 @@ public import Init.Grind.Tactics
public section
attribute [grind cases eager] And Prod False Empty True PUnit Exists Subtype
attribute [grind cases eager] And False Empty True PUnit Exists Subtype Prod PProd MProd
attribute [grind cases] Or

View File

@@ -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

View File

@@ -20,6 +20,24 @@ class AddRightCancel (M : Type u) [Add M] where
/-- Addition is right-cancellative. -/
add_right_cancel : a b c : M, a + c = b + c a = b
class AddCommMonoid (M : Type u) extends Zero M, Add M where
/-- Zero is the right identity for addition. -/
add_zero : a : M, a + 0 = a
/-- Addition is commutative. -/
add_comm : a b : M, a + b = b + a
/-- Addition is associative. -/
add_assoc : a b c : M, a + b + c = a + (b + c)
attribute [instance 100] AddCommMonoid.toZero AddCommMonoid.toAdd
class AddCommGroup (M : Type u) extends AddCommMonoid M, Neg M, Sub M where
/-- Negation is the left inverse of addition. -/
neg_add_cancel : a : M, -a + a = 0
/-- Subtraction is addition of the negative. -/
sub_eq_add_neg : a b : M, a - b = a + -b
attribute [instance 100] AddCommGroup.toAddCommMonoid AddCommGroup.toNeg AddCommGroup.toSub
/--
A module over the natural numbers, i.e. a type with zero, addition, and scalar multiplication by natural numbers,
satisfying appropriate compatibilities.
@@ -28,25 +46,15 @@ Equivalently, an additive commutative monoid.
Use `IntModule` if the type has negation.
-/
class NatModule (M : Type u) extends Zero M, Add M, HMul Nat M M where
/-- Zero is the right identity for addition. -/
add_zero : a : M, a + 0 = a
/-- Addition is commutative. -/
add_comm : a b : M, a + b = b + a
/-- Addition is associative. -/
add_assoc : a b c : M, a + b + c = a + (b + c)
class NatModule (M : Type u) extends AddCommMonoid M where
/-- Scalar multiplication by natural numbers. -/
[nsmul : HMul Nat M M]
/-- Scalar multiplication by zero is zero. -/
zero_hmul : a : M, 0 * a = 0
/-- Scalar multiplication by one is the identity. -/
one_hmul : a : M, 1 * a = a
/-- Scalar multiplication is distributive over addition in the natural numbers. -/
add_hmul : n m : Nat, a : M, (n + m) * a = n * a + m * a
/-- Scalar multiplication of zero is zero. -/
hmul_zero : n : Nat, n * (0 : M) = 0
/-- Scalar multiplication is distributive over addition in the module. -/
hmul_add : n : Nat, a b : M, n * (a + b) = n * a + n * b
zero_nsmul : a : M, 0 * a = 0
/-- Scalar multiplication by a successor. -/
add_one_nsmul : n : Nat, a : M, (n + 1) * a = n * a + a
attribute [instance 100] NatModule.toZero NatModule.toAdd NatModule.toHMul
attribute [instance 100] NatModule.toAddCommMonoid NatModule.nsmul
/--
A module over the integers, i.e. a type with zero, addition, negation, subtraction, and scalar multiplication by integers,
@@ -54,83 +62,54 @@ satisfying appropriate compatibilities.
Equivalently, an additive commutative group.
-/
class IntModule (M : Type u) extends Zero M, Add M, Neg M, Sub M where
class IntModule (M : Type u) extends AddCommGroup M where
/-- Scalar multiplication by natural numbers. -/
[hmulNat : HMul Nat M M]
[nsmul : HMul Nat M M]
/-- Scalar multiplication by integers. -/
[hmulInt : HMul Int M M]
/-- Zero is the right identity for addition. -/
add_zero : a : M, a + 0 = a
/-- Addition is commutative. -/
add_comm : a b : M, a + b = b + a
/-- Addition is associative. -/
add_assoc : a b c : M, a + b + c = a + (b + c)
[zsmul : HMul Int M M]
/-- Scalar multiplication by zero is zero. -/
zero_hmul : a : M, (0 : Int) * a = 0
zero_zsmul : a : M, (0 : Int) * a = 0
/-- Scalar multiplication by one is the identity. -/
one_hmul : a : M, (1 : Int) * a = a
one_zsmul : a : M, (1 : Int) * a = a
/-- Scalar multiplication is distributive over addition in the integers. -/
add_hmul : n m : Int, a : M, (n + m) * a = n * a + m * a
/-- Scalar multiplication of zero is zero. -/
hmul_zero : n : Int, n * (0 : M) = 0
/-- Scalar multiplication is distributive over addition in the module. -/
hmul_add : n : Int, a b : M, n * (a + b) = n * a + n * b
/-- Negation is the left inverse of addition. -/
neg_add_cancel : a : M, -a + a = 0
/-- Subtraction is addition of the negative. -/
sub_eq_add_neg : a b : M, a - b = a + -b
add_zsmul : n m : Int, a : M, (n + m) * a = n * a + m * a
/-- Scalar multiplication by natural numbers is consistent with scalar multiplication by integers. -/
hmul_nat : n : Nat, a : M, (n : Int) * a = n * a
zsmul_natCast_eq_nsmul : n : Nat, a : M, (n : Int) * a = n * a
namespace NatModule
variable {M : Type u} [NatModule M]
theorem zero_add (a : M) : 0 + a = a := by
rw [add_comm, add_zero]
theorem mul_hmul (n m : Nat) (a : M) : (n * m) * a = n * (m * a) := by
induction n with
| zero => simp [zero_hmul]
| succ n ih =>
rw [Nat.add_one_mul, add_hmul, ih, add_hmul, one_hmul]
instance (priority := 100) (M : Type u) [NatModule M] : SMul Nat M where
smul a x := a * x
end NatModule
attribute [instance 100] IntModule.toAddCommGroup IntModule.zsmul
namespace IntModule
attribute [instance 100] IntModule.toZero IntModule.toAdd IntModule.toNeg IntModule.toSub
IntModule.hmulNat IntModule.hmulInt
instance toNatModule (M : Type u) [i : IntModule M] : NatModule M :=
{ i with
hMul := i.hmulNat.hMul
zero_hmul := by simp [ hmul_nat, zero_hmul]
one_hmul := by simp [ hmul_nat, one_hmul]
hmul_zero := by simp [ hmul_nat, hmul_zero]
add_hmul := by simp [ hmul_nat, add_hmul]
hmul_add := by simp [ hmul_nat, hmul_add] }
instance (priority := 100) (M : Type u) [IntModule M] : SMul Nat M where
smul a x := a * x
instance (priority := 100) (M : Type u) [IntModule M] : SMul Int M where
smul a x := a * x
variable {M : Type u} [IntModule M]
instance (priority := 100) toNatModule [I : IntModule M] : NatModule M :=
{ I with
zero_nsmul a := by rw [ zsmul_natCast_eq_nsmul, Int.natCast_zero, zero_zsmul]
add_one_nsmul n a := by rw [ zsmul_natCast_eq_nsmul, Int.natCast_add_one, add_zsmul,
zsmul_natCast_eq_nsmul, one_zsmul] }
end IntModule
namespace AddCommMonoid
variable {M : Type u} [AddCommMonoid M]
theorem zero_add (a : M) : 0 + a = a := by
rw [add_comm, add_zero]
theorem add_neg_cancel (a : M) : a + -a = 0 := by
rw [add_comm, neg_add_cancel]
theorem add_left_comm (a b c : M) : a + (b + c) = b + (a + c) := by
rw [ add_assoc, add_assoc, add_comm a]
end AddCommMonoid
namespace AddCommGroup
variable {M : Type u} [AddCommGroup M]
open AddCommMonoid
theorem add_neg_cancel (a : M) : a + -a = 0 := by
rw [add_comm, neg_add_cancel]
theorem add_left_inj {a b : M} (c : M) : a + c = b + c a = b :=
fun h => by simpa [add_assoc, add_neg_cancel, add_zero] using (congrArg (· + -c) h),
fun g => congrArg (· + c) g
@@ -175,35 +154,95 @@ theorem add_sub_cancel {a b : M} : a + b - b = a := by
theorem sub_add_cancel {a b : M} : a - b + b = a := by
rw [sub_eq_add_neg, add_assoc, neg_add_cancel, add_zero]
theorem neg_hmul (n : Int) (a : M) : (-n) * a = - (n * a) := by
theorem neg_eq_iff (a b : M) : -a = b a = -b := by
constructor
· intro h
rw [ neg_neg a, h]
· intro h
rw [ neg_neg b, h]
end AddCommGroup
namespace NatModule
variable {M : Type u} [NatModule M]
theorem one_nsmul (a : M) : 1 * a = a := by
rw [ Nat.zero_add 1, add_one_nsmul, zero_nsmul, AddCommMonoid.zero_add]
theorem add_nsmul (n m : Nat) (a : M) : (n + m) * a = n * a + m * a := by
induction m with
| zero => rw [Nat.add_zero, zero_nsmul, AddCommMonoid.add_zero]
| succ m ih => rw [add_one_nsmul, Nat.add_assoc, add_one_nsmul, ih, AddCommMonoid.add_assoc]
theorem nsmul_zero (n : Nat) : n * (0 : M) = 0 := by
induction n with
| zero => rw [zero_nsmul]
| succ n ih => rw [add_one_nsmul, ih, AddCommMonoid.zero_add]
theorem nsmul_add (n : Nat) (a b : M) : n * (a + b) = n * a + n * b := by
induction n with
| zero => rw [zero_nsmul, zero_nsmul, zero_nsmul, AddCommMonoid.zero_add]
| succ n ih => rw [add_one_nsmul, add_one_nsmul, add_one_nsmul, ih, AddCommMonoid.add_assoc,
AddCommMonoid.add_left_comm (n * b), AddCommMonoid.add_assoc]
theorem mul_nsmul (n m : Nat) (a : M) : (n * m) * a = n * (m * a) := by
induction n with
| zero => simp [zero_nsmul]
| succ n ih =>
rw [Nat.add_one_mul, add_nsmul, ih, add_nsmul, one_nsmul]
instance (priority := 100) (M : Type u) [NatModule M] : SMul Nat M where
smul a x := a * x
end NatModule
namespace IntModule
open NatModule AddCommGroup
instance (priority := 100) (M : Type u) [IntModule M] : SMul Int M where
smul a x := a * x
variable {M : Type u} [IntModule M]
theorem neg_zsmul (n : Int) (a : M) : (-n) * a = - (n * a) := by
apply (add_left_inj (n * a)).mp
rw [ add_hmul, Int.add_left_neg, zero_hmul, neg_add_cancel]
rw [ add_zsmul, Int.add_left_neg, zero_zsmul, neg_add_cancel]
theorem hmul_neg (n : Int) (a : M) : n * (-a) = - (n * a) := by
theorem zsmul_zero (n : Int) : n * (0 : M) = 0 := by
match n with
| (n : Nat) => rw [zsmul_natCast_eq_nsmul, NatModule.nsmul_zero]
| -(n + 1 : Nat) => rw [neg_zsmul, zsmul_natCast_eq_nsmul, NatModule.nsmul_zero, neg_zero]
theorem zsmul_add (n : Int) (a b : M) : n * (a + b) = n * a + n * b := by
match n with
| (n : Nat) => rw [zsmul_natCast_eq_nsmul, NatModule.nsmul_add, zsmul_natCast_eq_nsmul, zsmul_natCast_eq_nsmul]
| -(n + 1 : Nat) => rw [neg_zsmul, zsmul_natCast_eq_nsmul, NatModule.nsmul_add,
neg_zsmul, zsmul_natCast_eq_nsmul, neg_zsmul, zsmul_natCast_eq_nsmul, neg_add]
theorem zsmul_neg (n : Int) (a : M) : n * (-a) = - (n * a) := by
apply (add_left_inj (n * a)).mp
rw [ hmul_add, neg_add_cancel, neg_add_cancel, hmul_zero]
rw [ zsmul_add, neg_add_cancel, neg_add_cancel, zsmul_zero]
theorem hmul_sub (k : Int) (a b : M) : k * (a - b) = k * a - k * b := by
rw [sub_eq_add_neg, hmul_add, hmul_neg, sub_eq_add_neg]
theorem zsmul_sub (k : Int) (a b : M) : k * (a - b) = k * a - k * b := by
rw [sub_eq_add_neg, zsmul_add, zsmul_neg, sub_eq_add_neg]
theorem sub_hmul (k₁ k₂ : Int) (a : M) : (k₁ - k₂) * a = k₁ * a - k₂ * a := by
rw [Int.sub_eq_add_neg, add_hmul, neg_hmul, sub_eq_add_neg]
theorem sub_zsmul (k₁ k₂ : Int) (a : M) : (k₁ - k₂) * a = k₁ * a - k₂ * a := by
rw [Int.sub_eq_add_neg, add_zsmul, neg_zsmul, sub_eq_add_neg]
theorem nat_zero_hmul (a : M) : (0 : Nat) * a = 0 := by
rw [ hmul_nat, Int.natCast_zero, zero_hmul]
private theorem nat_mul_hmul (n : Nat) (m : Int) (a : M) :
private theorem mul_zsmul_aux (n : Nat) (m : Int) (a : M) :
((n : Int) * m) * a = (n : Int) * (m * a) := by
induction n with
| zero => simp [zero_hmul]
| zero => simp [zero_zsmul]
| succ n ih =>
rw [Int.natCast_add, Int.add_mul, add_hmul, Int.natCast_one,
Int.one_mul, add_hmul, one_hmul, ih]
rw [Int.natCast_add, Int.add_mul, add_zsmul, Int.natCast_one,
Int.one_mul, add_zsmul, one_zsmul, ih]
theorem mul_hmul (n m : Int) (a : M) : (n * m) * a = n * (m * a) := by
theorem mul_zsmul (n m : Int) (a : M) : (n * m) * a = n * (m * a) := by
match n with
| (n : Nat) => exact nat_mul_hmul n m a
| -(n + 1 : Nat) => rw [Int.neg_mul, neg_hmul, nat_mul_hmul, neg_hmul]
| (n : Nat) => exact mul_zsmul_aux n m a
| -(n + 1 : Nat) => rw [Int.neg_mul, neg_zsmul, mul_zsmul_aux, neg_zsmul]
end IntModule
@@ -225,31 +264,35 @@ export NoNatZeroDivisors (no_nat_zero_divisors)
namespace NoNatZeroDivisors
/-- Alternative constructor for `NoNatZeroDivisors` when we have an `IntModule`. -/
def mk' {α} [IntModule α] (eq_zero_of_mul_eq_zero : (k : Nat) (a : α), k 0 k * a = 0 a = 0) : NoNatZeroDivisors α where
def mk' {α} [IntModule α]
(eq_zero_of_mul_eq_zero : (k : Nat) (a : α), k 0 k * a = 0 a = 0) :
NoNatZeroDivisors α where
no_nat_zero_divisors k a b h₁ h₂ := by
rw [ IntModule.sub_eq_zero_iff, IntModule.hmul_nat, IntModule.hmul_nat, IntModule.hmul_sub, IntModule.hmul_nat] at h₂
rw [ IntModule.sub_eq_zero_iff]
rw [ AddCommGroup.sub_eq_zero_iff, IntModule.zsmul_natCast_eq_nsmul,
IntModule.zsmul_natCast_eq_nsmul, IntModule.zsmul_sub,
IntModule.zsmul_natCast_eq_nsmul] at h₂
rw [ AddCommGroup.sub_eq_zero_iff]
apply eq_zero_of_mul_eq_zero k (a - b) h₁ h₂
theorem eq_zero_of_mul_eq_zero {α : Type u} [NatModule α] [NoNatZeroDivisors α] {k : Nat} {a : α}
: k 0 k * a = 0 a = 0 := by
intro h₁ h₂
replace h₁ : k 0 := by intro h; simp [h] at h₁
exact no_nat_zero_divisors k a 0 h₁ (by rwa [NatModule.hmul_zero])
exact no_nat_zero_divisors k a 0 h₁ (by rwa [NatModule.nsmul_zero])
end NoNatZeroDivisors
instance [ToInt α (IntInterval.co lo hi)] [IntModule α] [ToInt.Zero α (IntInterval.co lo hi)] [ToInt.Add α (IntInterval.co lo hi)] : ToInt.Neg α (IntInterval.co lo hi) where
instance [ToInt α (IntInterval.co lo hi)] [AddCommGroup α] [ToInt.Zero α (IntInterval.co lo hi)] [ToInt.Add α (IntInterval.co lo hi)] : ToInt.Neg α (IntInterval.co lo hi) where
toInt_neg x := by
have := (ToInt.Add.toInt_add (-x) x).symm
rw [IntModule.neg_add_cancel, ToInt.Zero.toInt_zero, ToInt.Zero.wrap_zero (α := α)] at this
rw [AddCommGroup.neg_add_cancel, ToInt.Zero.toInt_zero, ToInt.Zero.wrap_zero (α := α)] at this
rw [IntInterval.wrap_eq_wrap_iff] at this
simp at this
rw [ ToInt.wrap_toInt]
rw [IntInterval.wrap_eq_wrap_iff]
simpa
instance [ToInt α (IntInterval.co lo hi)] [IntModule α] [ToInt.Add α (IntInterval.co lo hi)] [ToInt.Neg α (IntInterval.co lo hi)] : ToInt.Sub α (IntInterval.co lo hi) :=
ToInt.Sub.of_sub_eq_add_neg IntModule.sub_eq_add_neg (by simp)
instance [ToInt α (IntInterval.co lo hi)] [AddCommGroup α] [ToInt.Add α (IntInterval.co lo hi)] [ToInt.Neg α (IntInterval.co lo hi)] : ToInt.Sub α (IntInterval.co lo hi) :=
ToInt.Sub.of_sub_eq_add_neg AddCommGroup.sub_eq_add_neg (by simp)
end Lean.Grind

View File

@@ -19,9 +19,9 @@ variable [NatModule α]
-- Helper instance for `ac_rfl`
local instance : Std.Associative (· + · : α α α) where
assoc := NatModule.add_assoc
assoc := AddCommMonoid.add_assoc
local instance : Std.Commutative (· + · : α α α) where
comm := NatModule.add_comm
comm := AddCommMonoid.add_comm
@[local simp] private theorem exists_true : (_ : α), True := 0, trivial
@@ -33,10 +33,10 @@ def Q := Quot (r α)
variable {α}
theorem r_rfl (a : α × α) : r α a a := by
cases a; refine 0, ?_; simp [NatModule.add_zero]; ac_rfl
cases a; refine 0, ?_; simp [AddCommMonoid.add_zero]; ac_rfl
theorem r_sym {a b : α × α} : r α a b r α b a := by
cases a; cases b; simp [r]; intro h w; refine h, ?_; simp [w, NatModule.add_comm]
cases a; cases b; simp [r]; intro h w; refine h, ?_; simp [w, AddCommMonoid.add_comm]
theorem r_trans {a b c : α × α} : r α a b r α b c r α a c := by
cases a; cases b; cases c;
@@ -63,20 +63,20 @@ def Q.liftOn₂ (q₁ q₂ : Q α)
induction q₂ using Quot.ind
apply h; assumption; apply r_rfl
attribute [local simp] Q.mk Q.liftOn₂ NatModule.add_zero
attribute [local simp] Q.mk Q.liftOn₂ AddCommMonoid.add_zero
def Q.ind {β : Q α Prop} (mk : (a : α × α), β (Q.mk a)) (q : Q α) : β q :=
Quot.ind mk q
@[local simp] def hmulNat (n : Nat) (q : Q α) : (Q α) :=
@[local simp] def nsmul (n : Nat) (q : Q α) : (Q α) :=
q.liftOn (fun (a, b) => Q.mk (n * a, n * b))
(by intro (a₁, b₁) (a₂, b₂)
simp; intro k h; apply Quot.sound; simp
refine n * k, ?_
replace h := congrArg (fun x : α => n * x) h
simpa [NatModule.hmul_add] using h)
simpa [NatModule.nsmul_add] using h)
@[local simp] def hmulInt (n : Int) (q : Q α) : (Q α) :=
@[local simp] def zsmul (n : Int) (q : Q α) : (Q α) :=
q.liftOn (fun (a, b) => if n < 0 then Q.mk (n.natAbs * b, n.natAbs * a) else Q.mk (n.natAbs * a, n.natAbs * b))
(by intro (a₁, b₁) (a₂, b₂)
simp; intro k h;
@@ -84,11 +84,11 @@ def Q.ind {β : Q α → Prop} (mk : ∀ (a : α × α), β (Q.mk a)) (q : Q α)
· apply Quot.sound; simp
refine n.natAbs * k, ?_
replace h := congrArg (fun x : α => n.natAbs * x) h
simpa [NatModule.hmul_add] using h.symm
simpa [NatModule.nsmul_add] using h.symm
· apply Quot.sound; simp
refine n.natAbs * k, ?_
replace h := congrArg (fun x : α => n.natAbs * x) h
simpa [NatModule.hmul_add] using h)
simpa [NatModule.nsmul_add] using h)
@[local simp] def sub (q₁ q₂ : Q α) : Q α :=
Q.liftOn₂ q₁ q₂ (fun (a, b) (c, d) => Q.mk (a + d, c + b))
@@ -115,8 +115,8 @@ def Q.ind {β : Q α → Prop} (mk : ∀ (a : α × α), β (Q.mk a)) (q : Q α)
exact k, h.symm)
attribute [local simp]
Quot.liftOn NatModule.add_zero NatModule.zero_add NatModule.one_hmul NatModule.zero_hmul NatModule.hmul_zero
NatModule.hmul_add NatModule.add_hmul
Quot.liftOn AddCommMonoid.add_zero AddCommMonoid.zero_add NatModule.one_nsmul NatModule.zero_nsmul NatModule.nsmul_zero
NatModule.nsmul_add NatModule.add_nsmul
@[local simp] def zero : Q α :=
Q.mk (0, 0)
@@ -150,29 +150,15 @@ theorem sub_eq_add_neg (a b : Q α) : sub a b = add a (neg b) := by
next a b =>
cases a; cases b; simp; apply Quot.sound; simp; refine 0, ?_; ac_rfl
theorem one_hmul (a : Q α) : hmulInt 1 a = a := by
theorem one_zsmul (a : Q α) : zsmul 1 a = a := by
induction a using Quot.ind
next a => cases a; simp
theorem zero_hmul (a : Q α) : hmulInt 0 a = zero := by
theorem zero_zsmul (a : Q α) : zsmul 0 a = zero := by
induction a using Quot.ind
next a => cases a; simp
theorem hmul_zero (a : Int) : hmulInt a (zero : Q α) = zero := by
simp
theorem hmul_add (a : Int) (b c : Q α) : hmulInt a (add b c) = add (hmulInt a b) (hmulInt a c) := by
induction b using Q.ind
induction c using Q.ind
next b c =>
cases b; cases c; simp
split <;>
· apply Quot.sound
refine 0, ?_
simp
ac_rfl
theorem add_hmul (a b : Int) (c : Q α) : hmulInt (a + b) c = add (hmulInt a c) (hmulInt b c) := by
theorem add_zsmul (a b : Int) (c : Q α) : zsmul (a + b) c = add (zsmul a c) (zsmul b c) := by
induction c using Q.ind
next c =>
rcases c with c₁, c₂; simp
@@ -183,7 +169,7 @@ theorem add_hmul (a b : Int) (c : Q α) : hmulInt (a + b) c = add (hmulInt a c)
rw [if_pos (by omega)]
apply Quot.sound
refine 0, ?_
rw [Int.natAbs_add_of_nonpos (by omega) (by omega), NatModule.add_hmul, NatModule.add_hmul]
rw [Int.natAbs_add_of_nonpos (by omega) (by omega), NatModule.add_nsmul, NatModule.add_nsmul]
ac_rfl
· split
· apply Quot.sound
@@ -213,23 +199,23 @@ theorem add_hmul (a b : Int) (c : Q α) : hmulInt (a + b) c = add (hmulInt a c)
rw [if_neg (by omega)]
apply Quot.sound
refine 0, ?_
rw [Int.natAbs_add_of_nonneg (by omega) (by omega), NatModule.add_hmul, NatModule.add_hmul]
rw [Int.natAbs_add_of_nonneg (by omega) (by omega), NatModule.add_nsmul, NatModule.add_nsmul]
ac_rfl
theorem hmul_nat (n : Nat) (a : Q α) : hmulInt (n : Int) a = hmulNat n a := by
theorem zsmul_natCast_eq_nsmul (n : Nat) (a : Q α) : zsmul (n : Int) a = nsmul n a := by
induction a using Q.ind
next a =>
rcases a with a₁, a₂; simp; omega
def ofNatModule : IntModule (Q α) := {
hmulNat := hmulNat,
hmulInt := hmulInt,
nsmul := nsmul,
zsmul := zsmul,
zero,
add, sub, neg,
add_comm, add_assoc, add_zero,
neg_add_cancel, sub_eq_add_neg,
one_hmul, zero_hmul, hmul_zero, hmul_add, add_hmul,
hmul_nat
one_zsmul, zero_zsmul, add_zsmul,
zsmul_natCast_eq_nsmul
}
attribute [instance] ofNatModule
@@ -257,7 +243,7 @@ private def rel (h : Equivalence (r α)) (q₁ q₂ : Q α) : Prop :=
private theorem rel_rfl (h : Equivalence (r α)) (q : Q α) : rel h q q := by
induction q using Quot.ind
simp [rel, NatModule.add_comm]
simp [rel, AddCommMonoid.add_comm]
private theorem helper (h : Equivalence (r α)) (q₁ q₂ : Q α) : q₁ = q₂ rel h q₁ q₂ := by
intro h; subst q₁; apply rel_rfl h
@@ -287,7 +273,7 @@ instance [NatModule α] [AddRightCancel α] [NoNatZeroDivisors α] : NoNatZeroDi
simp [r] at h₂
rcases h₂ with k', h₂
replace h₂ := AddRightCancel.add_right_cancel _ _ _ h₂
simp [ NatModule.hmul_add] at h₂
simp [ NatModule.nsmul_add] at h₂
replace h₂ := NoNatZeroDivisors.no_nat_zero_divisors k (a₁ + b₂) (a₂ + b₁) h₁ h₂
apply Quot.sound; simp [r]; exists 0; simp [h₂]
@@ -318,7 +304,7 @@ instance [Preorder α] [OrderedAdd α] : Preorder (OfNatModule.Q α) where
rcases a with a₁, a₂
change Q.mk _ Q.mk _
simp only [mk_le_mk]
simp [NatModule.add_comm]; exact Preorder.le_refl (a₁ + a₂)
simp [AddCommMonoid.add_comm]; exact Preorder.le_refl (a₁ + a₂)
le_trans {a b c} h₁ h₂ := by
induction a using Q.ind
induction b using Q.ind
@@ -337,12 +323,12 @@ attribute [-simp] Q.mk
@[local simp] private theorem mk_lt_mk [Preorder α] [OrderedAdd α] {a₁ a₂ b₁ b₂ : α} :
Q.mk (a₁, a₂) < Q.mk (b₁, b₂) a₁ + b₂ < a₂ + b₁ := by
simp [Preorder.lt_iff_le_not_le, NatModule.add_comm]
simp [Preorder.lt_iff_le_not_le, AddCommMonoid.add_comm]
@[local simp] private theorem mk_pos [Preorder α] [OrderedAdd α] {a₁ a₂ : α} :
0 < Q.mk (a₁, a₂) a₂ < a₁ := by
change Q.mk (0,0) < _ _
simp [mk_lt_mk, NatModule.zero_add]
simp [mk_lt_mk, AddCommMonoid.zero_add]
@[local simp]
theorem toQ_le [Preorder α] [OrderedAdd α] {a b : α} : toQ a toQ b a b := by

Some files were not shown because too many files have changed in this diff Show More