Compare commits

...

2917 Commits

Author SHA1 Message Date
Leonardo de Moura
4187edf5e7 chore: update stage0 2022-09-06 17:26:15 -07:00
Leonardo de Moura
7bc9c12462 chore: remove [inline] from parser combinators 2022-09-06 17:24:50 -07:00
Leonardo de Moura
f4fbf92313 fix: make privateToUserNameAux more robust 2022-09-06 17:15:56 -07:00
Leonardo de Moura
85851d0c43 fix: bug at PullFunDecls 2022-09-06 17:15:56 -07:00
Sebastian Ullrich
bb1c5a7a49 doc: ink all .lean files in doc/ 2022-09-06 21:12:19 +02:00
Leonardo de Moura
56f0d6c183 feat: specialize partial applications of local functions 2022-09-06 06:44:33 -07:00
Leonardo de Moura
c769808a4e chore: add TODO 2022-09-05 19:35:17 -07:00
Leonardo de Moura
1812e86c7f feat: eta expand partial applications of functions that take local instances as arguments 2022-09-05 19:33:22 -07:00
Leonardo de Moura
bf44e9fb2f fix: bug at inferProjType for LCNF 2022-09-05 19:23:35 -07:00
Leonardo de Moura
3e210d9f26 chore: helper functions, missing instance 2022-09-05 19:20:31 -07:00
Leonardo de Moura
7113d71cd2 doc: LCNF/Simp.lean docstrings 2022-09-05 17:36:35 -07:00
Leonardo de Moura
1207e5e285 feat: erase cases when all alternatives are the same 2022-09-05 17:22:54 -07:00
Leonardo de Moura
58d8224d9e feat: add LCNF cases default 2022-09-05 14:08:14 -07:00
Chris Lovett
cc95456639 doc: add documentation on monads (#1505)
* doc: add documentation on functors.

* fix: make comments green

* minor tweaks

* doc: add section on Applicatives.

* doc: add some more info on the laws from Mario.

* doc: add law list and move lazy evaluation up so the chapter ends properly.

* doc: Add something on seqLeft and seqRight.

* doc: add section on monads.

* doc: fix some typos.

* doc: switch to LeanInk for chaper on Monads.

* doc: remove old files.

* doc: fix mdbook test errors.

* doc: add part 4: readers

* doc: add section on State monads

* doc: fix some typos and add some more details.

* doc: fix typos and add some CR feedback.

* doc: add Except monad section.

* doc: add info on monad transformers.

* Delete transformers.lean.md

* doc: fix some typos.

* doc: fix typos and move forward reference to monad lifting.

* doc: Update `State` to `StateM`

* doc: fix references to State to become StateM.

* doc: generalize indexOf implementation.

* doc: add chapter on monad laws and move "law" sections to this chapter to avoid redundancy.

* doc: add theorem

* Delete laws.lean.md

* doc: fix some typos.

* doc: fix broken link.

* doc: fox typos.

* fix: language changed from "us" to "you".

* doc: fix code review comments.

* doc: some word smithing

* doc: some word smithing and sample simplification.

* doc: add bad_option_map example.

* doc: add side note on `return` statement and fix heading level consistency.

* Add `withReader` info

* doc: change language from us, our, your, we, we'll, we've to "you"

* doc: add some forward links.

* doc: put spaces around colon in function  arguments like "(x : List Nat)"

* doc:
Add backticks on map
Remove commands on multiline structure instance
Fix centerdot
Add "one of"

* doc: Remove info about Functor in other languages.

* doc:
add info on <$> being left associative
remove another forward reference to monad
fix typo `operatoions`
remove unneccesary parens after <$>

* doc:
fix Type u -> Type v
fix you -> your
use `let val? ← IO.getEnv name`
in Readers call it "context" rather than "state".

* doc: fix withReader docs
use 'context' to describe the ReaderM state.
remove "trivial"
type inference => Lean
"abstract classes" => "abstract structures"
remove unnecessary parens

* doc: fix bug in explanation of `let x ← readerFunc2`
Fix explanation of equivalence between `def f (a : Nat) : String` and `def f : Nat → String`

* doc: move hasSomeItemGreaterThan to Except.lean
Add validateList List.anyM example.
fix `def f (a : Nat) : String` language.

* doc: fix "What transformation are you referring to"

* doc: fix typo.

* doc: add missing period.

* doc: fix validateList

* doc: explain `λ` notation.

* doc: reword the map, seq, bind comparison.

* doc: fix some more 'reader state' to 'reader context' language

* doc: fix wrote statement about return only works in do blocks.

* doc: fix typo

Co-authored-by: Sebastian Ullrich <sebasti@nullri.ch>

* doc: improve language

Co-authored-by: Sebastian Ullrich <sebasti@nullri.ch>

* doc: fix typo

Co-authored-by: Sebastian Ullrich <sebasti@nullri.ch>

* Add info on what a do block is doing for you.

* doc: define definitionally equal

* doc: make `readerFunc3.run env` canonical.

* doc: remove unnecessary parens.

* doc: fix typos

* doc: make List.map a bit more clear in the intro to Functors.

* doc: simplify readerFunc3WithReader

* doc: switch to svg for diagram so it works better on dark themes.

* doc: align nodes in diagram and convert to svg.

* doc: simplify playGame using while true.

* doc: drop confusing statement about "definitionally equal"

* doc: switch to `import Lean.Data.HashMap`

* doc: fix typo "operatoins"

* doc: update diagram to add more info and polish the intro paragraphs so they better match the actual contents of each chapter.

* doc: fix typo

* doc: fix typo.

Co-authored-by: Sebastian Ullrich <sebasti@nullri.ch>
2022-09-05 13:33:15 -07:00
Gabriel Ebner
8e7e58fc38 feat: synchronous operations for Channel 2022-09-05 08:52:46 -07:00
Gabriel Ebner
213cb322be chore: add test 2022-09-05 08:52:46 -07:00
Gabriel Ebner
c4d421b3de feat: Channel 2022-09-05 08:52:46 -07:00
Gabriel Ebner
7c552380da feat: Mutex, Condvar 2022-09-05 08:52:46 -07:00
Gabriel Ebner
c2f1e01b3b feat: Promise 2022-09-05 08:52:46 -07:00
Gabriel Ebner
451f6df5df fix: IO.waitAny requires nonempty list 2022-09-05 08:52:46 -07:00
Gabriel Ebner
20f41deea7 feat: add Eval instance for BaseIO 2022-09-05 08:52:46 -07:00
Gabriel Ebner
b80775df6f chore: add nonempty instance for monads 2022-09-05 08:52:46 -07:00
Gabriel Ebner
3bd0379993 chore: add nonempty instance for Task 2022-09-05 08:52:46 -07:00
Gabriel Ebner
f7bae54b09 chore: resurrect Std.Queue 2022-09-05 08:52:46 -07:00
Gabriel Ebner
22c3ec3996 chore: generalize IO.sleep to BaseIO 2022-09-05 08:52:46 -07:00
Leonardo de Moura
553addc078 feat: alpha equivalence for LCNF code 2022-09-05 08:06:05 -07:00
Leonardo de Moura
34f3fcdee5 chore: fix test 2022-09-05 06:58:32 -07:00
Leonardo de Moura
fde8d35bbb refactor: declare passes when declaring transformations 2022-09-05 06:58:32 -07:00
Leonardo de Moura
1c41a750ed feat: add ReduceJpArity compiler pass 2022-09-05 06:58:32 -07:00
Mario Carneiro
a73e02e5fc doc: fix typo 2022-09-05 10:24:57 +02:00
Leonardo de Moura
e0197b4e09 feat: add bindCases
It is similar to `Code.bind` but has special support for `inlineMatcher`
2022-09-04 19:04:21 -07:00
Leonardo de Moura
d0600b3750 fix: incorrect binder name being used
cc @hargoniX
2022-09-04 16:56:42 -07:00
Leonardo de Moura
abd37d8fd1 feat: check binder names at LCNF/Check.lean 2022-09-04 16:55:42 -07:00
Leonardo de Moura
01ca711859 feat: add PullFunDecls.lean 2022-09-04 16:44:45 -07:00
Leonardo de Moura
df16c5a0e7 feat: add Code.collectUsed and FunDecl.collectUsed 2022-09-04 13:05:48 -07:00
Leonardo de Moura
b3c5184772 chore: remove dead code 2022-09-04 07:14:01 -07:00
Henrik Böving
4ee9080a9b feat: basic compiler pass tests 2022-09-03 19:55:53 -07:00
Henrik Böving
32157f0e42 feat: Basic compiler testing framework 2022-09-03 19:55:53 -07:00
E.W.Ayers
30b44c03b4 fix: map fn should have explict args 2022-09-03 19:45:08 -07:00
E.W.Ayers
37745b5174 feat: intersectBy 2022-09-03 19:45:08 -07:00
E.W.Ayers
9cd24caee6 feat: utils for RBMap 2022-09-03 19:45:08 -07:00
Leonardo de Moura
56ea3af6e2 doc: Compiler/LCNF/Simp.lean 2022-09-03 19:44:10 -07:00
Leonardo de Moura
9f44e9c858 feat: simplify nested cases on the same discriminant 2022-09-03 19:44:10 -07:00
Mario Carneiro
bff9cdbfb3 doc: update lean 3 -> lean 4 in declarations.md 2022-09-03 08:35:37 -07:00
Leonardo de Moura
5478485de1 feat: allow "small prefix" at cases on cases optimization 2022-09-03 08:21:11 -07:00
Leonardo de Moura
bc88b0307e feat: cases on cases for new LCNF simplifier 2022-09-03 07:54:19 -07:00
Chris Lovett
e8335240d8 doc: update the mdbook instructions (#1521) 2022-09-03 11:08:38 +02:00
Mario Carneiro
37252e5fa7 chore: remove Bootstrap package 2022-09-02 16:39:03 -07:00
Leonardo de Moura
196c9537f2 feat: eta reduction at toLCNF 2022-09-02 06:31:06 -07:00
Leonardo de Moura
d5dcd5e856 feat: eta-expand local function declarations that are not being inlined 2022-09-02 05:22:41 -07:00
Mario Carneiro
158e182b8b chore: move Bootstrap.Dynamic -> Init.Dynamic 2022-09-02 04:36:54 -07:00
Mario Carneiro
07b1b54d03 chore: update stage0 2022-09-02 04:36:54 -07:00
Mario Carneiro
060290619e chore: move Bootstrap.Dynamic -> Init.Dynamic (part 1) 2022-09-02 04:36:54 -07:00
Leonardo de Moura
e3a8574e15 perf: workaround for issue #316 2022-09-02 04:15:02 -07:00
Leonardo de Moura
dfdbec51ad fix: typo 2022-09-02 03:41:49 -07:00
Leonardo de Moura
baf4f1c152 perf: simpValue? before inlineApp? 2022-09-02 03:20:59 -07:00
Leonardo de Moura
6297b2efe7 feat: do not eagerly simplify function declarations that will be inlined 2022-09-01 21:13:14 -07:00
Leonardo de Moura
21a7066d77 feat: inline type class projections 2022-09-01 20:52:08 -07:00
Leonardo de Moura
0ed46003c6 feat: add CodeDecl helper type 2022-09-01 20:52:08 -07:00
Leonardo de Moura
0b0bd968b0 feat: support for inlining join points 2022-09-01 20:52:08 -07:00
Leonardo de Moura
61edf19334 fix: allow LCNF discriminant to have any type 2022-09-01 20:52:08 -07:00
Leonardo de Moura
30c75b4b88 feat: add simpCasesOnCtor 2022-09-01 20:52:08 -07:00
Leonardo de Moura
255d34d2ac feat: add simpValue? back 2022-09-01 20:52:08 -07:00
Gabriel Ebner
3d6006885b feat: use widget source from first snapshot 2022-09-01 16:57:03 +02:00
Gabriel Ebner
4246d98547 fix: remove unnecessary BaseIO in AsyncList 2022-09-01 16:57:03 +02:00
Gabriel Ebner
9bfbabb9df fix: do not fail widget request after #exit 2022-09-01 16:57:03 +02:00
Gabriel Ebner
87a6dd56b8 feat: use RPC method from first snapshot
There is no need to wait for further snapshots if the RPC method was already found in an earlier snapshot, or even built-in.
2022-09-01 16:57:03 +02:00
Leonardo de Moura
29eddad325 chore: only check if compiler.check is set to true 2022-09-01 07:18:47 -07:00
Leonardo de Moura
cedf9e980b feat: check LCNF parameters 2022-09-01 07:17:53 -07:00
Leonardo de Moura
9874ef3c66 feat: check whether LetDecl and FunDecl match their values in the LCNF local context 2022-09-01 07:05:07 -07:00
Marcus Rossel
a2a39882d5 feat: add Hashable for Subtype 2022-09-01 06:11:23 -07:00
Leonardo de Moura
d96bf8a633 chore: restore accidentally deleted test
25447af13c
2022-09-01 06:06:03 -07:00
Leonardo de Moura
c201133d4d feat: LCNF local context dead variable checker
This commit also fixes a few local declaration leaks.
2022-08-31 21:07:21 -07:00
Leonardo de Moura
ddab48a154 fix: erase dead variables 2022-08-31 20:43:13 -07:00
Leonardo de Moura
a81c9f6c09 chore: update stage0 2022-08-31 20:21:28 -07:00
Leonardo de Moura
d00627364c feat: add simp compiler pass 2022-08-31 18:10:32 -07:00
Leonardo de Moura
ba0835e387 feat: refresh binder names during internalization 2022-08-31 18:10:32 -07:00
Leonardo de Moura
25447af13c feat: new code inliner 2022-08-31 18:10:32 -07:00
Sebastian Ullrich
2e98726973 fix: levelMVarToParam must update levelNames 2022-08-31 17:57:07 -07:00
Sebastian Ullrich
e075b54f22 fix: collision between implicit and auto-bound level names 2022-08-31 17:57:07 -07:00
Mario Carneiro
ce3c0c0e6b feat: add TR versions of Nat.{fold, any, all, repeat} 2022-08-31 17:52:59 -07:00
Sebastian Ullrich
a657a638f0 feat: sub-info tree level hover 2022-08-31 17:49:43 -07:00
Sebastian Ullrich
4050227e5d chore: revert marking internal notes as parser/elab docstrings 2022-08-31 17:49:43 -07:00
Sebastian Ullrich
b9152a5296 refactor: move, generalize findSyntaxStack? 2022-08-31 17:49:43 -07:00
Henrik Böving
c1949e05e0 feat: migrate to new pass manager 2022-08-31 16:28:07 -07:00
Henrik Böving
5d834f3f0e chore: update stage0 2022-08-31 16:28:07 -07:00
Henrik Böving
fe63bd2e8e feat: basic pass manager 2022-08-31 16:28:07 -07:00
Sebastian Ullrich
98145ad8ba chore: not a docstring 2022-08-31 22:19:27 +02:00
Mario Carneiro
ebb5b97d73 chore: move Bootstrap.Data -> Lean.Data 2022-08-31 11:48:57 -07:00
Mario Carneiro
c089639b19 refactor: Init.SimpLemmas proof golf / cleanup 2022-08-31 11:27:58 -07:00
Leonardo de Moura
2fc38fb118 feat: instantiateTypeLevelParams and instantiateValueLevelParams for LCNF.Decl 2022-08-30 20:20:39 -07:00
Leonardo de Moura
a0b47195ba fix: fixes #1547 2022-08-30 11:45:05 -07:00
Leonardo de Moura
b6f0bdc542 chore: add Array.mapMono 2022-08-30 11:45:05 -07:00
Leonardo de Moura
c451bf0c91 feat: add simpFunDecl 2022-08-30 11:45:05 -07:00
Mario Carneiro
b2b02295b0 chore: move ShareCommon to Init / Lean 2022-08-30 07:51:43 -07:00
Leonardo de Moura
ca80bc52dc feat: LCNF.simp .let case 2022-08-29 09:52:16 -07:00
Leonardo de Moura
7b161d33d1 refactor: add MonadFVarSubst class 2022-08-29 09:52:16 -07:00
Mario Carneiro
6a7ccb5797 refactor: generalize ShareCommon to a typeclass (#1537) 2022-08-29 09:34:38 -07:00
Mario Carneiro
850ee17346 chore: move Bootstrap.System.Uri to Init 2022-08-29 08:06:30 -07:00
Siddharth Bhat
a7b128fee1 doc: explanations for LCNF. 2022-08-29 07:17:25 -07:00
Mario Carneiro
0efbc0bc03 chore: remove BinomialHeap, DList, Stack, Queue
These are moving to std4.
2022-08-29 07:07:53 -07:00
Mario Carneiro
bf89c5a0f5 chore: move Std -> Bootstrap 2022-08-29 01:26:12 -07:00
Mario Carneiro
31784c9a24 doc: documentation for Init.Core 2022-08-29 00:41:24 -07:00
Mario Carneiro
5658000396 refactor: golf proof of funext 2022-08-28 19:01:46 -07:00
Leonardo de Moura
062d4728a1 feat: more LCNF update functions
and bug fixes at CSE
2022-08-28 19:00:49 -07:00
Leonardo de Moura
5552d610e8 chore: missing updateCases! 2022-08-28 16:30:54 -07:00
Leonardo de Moura
e80028b7d1 feat: add pure field to LetDecl, add helper functions for updating LCNF code
The update functions try to minimize the amount of memory allocation
2022-08-28 08:55:35 -07:00
Leonardo de Moura
4f5a014170 feat: add Array.mapMonoM 2022-08-28 08:55:35 -07:00
Leonardo de Moura
d5fa178fc3 feat: modify FVarSubst used in the new code generator 2022-08-28 08:55:35 -07:00
Leonardo de Moura
6a9f8ad919 fix: Compiler/LCNF/ElimDead.lean 2022-08-28 08:55:35 -07:00
Mario Carneiro
f93914e613 fix: prove decidable_of_decidable_of_eq without cast 2022-08-28 08:32:00 -07:00
Mario Carneiro
d4c7d0f266 chore: remove def implies 2022-08-28 07:57:56 -07:00
Leonardo de Moura
cd0dd4cc2f feat: start simp for new LCNF format 2022-08-27 19:59:31 -07:00
Leonardo de Moura
9446ae3056 feat: add cleanup function for CompilerM 2022-08-27 18:35:30 -07:00
Leonardo de Moura
30d8ae70f7 chore: remove workarounds 2022-08-27 10:56:15 -07:00
Leonardo de Moura
792ce8ce44 chore: update stage0 2022-08-27 10:46:06 -07:00
Leonardo de Moura
ee8e771445 fix: dotted name bug 2022-08-27 10:41:55 -07:00
Leonardo de Moura
0f40dfc063 feat: add FunDecl.etaExpand 2022-08-27 10:41:54 -07:00
Leonardo de Moura
11c8253f6c feat: more update functions for LCNF 2022-08-27 10:41:54 -07:00
Leonardo de Moura
bdf89b4d85 chore: add {crossEmoji} at failure 2022-08-27 10:41:54 -07:00
Sebastian Ullrich
48c1ddc807 chore: update stage0 2022-08-27 17:44:58 +02:00
Sebastian Ullrich
4562fcfbd7 chore: Nix: include orphan modules like lean.mk does 2022-08-27 17:41:46 +02:00
Sebastian Ullrich
fb408c024b fix: deleting built-in docstrings 2022-08-27 17:19:25 +02:00
Mario Carneiro
9bd886f37d fix: @[inheritDoc] on notation 2022-08-27 07:11:39 -07:00
Leonardo de Moura
0925051c51 chore: rename Reader to ReaderM
closes #1524
2022-08-26 20:59:17 -07:00
Sebastian Ullrich
12d7e839b0 doc: Stream.read/getLine 2022-08-26 20:55:09 -07:00
Sebastian Ullrich
b010805000 fix: Handle.read at EOF 2022-08-26 20:55:09 -07:00
Sebastian Ullrich
a69d7fb018 fix: remove broken Handle.isEof 2022-08-26 20:55:09 -07:00
Sebastian Ullrich
d23c19884b doc: read/getLine EOF behavior 2022-08-26 20:55:09 -07:00
Sebastian Ullrich
af7f5aa2a0 feat: dbgStackTrace 2022-08-26 20:52:51 -07:00
E.W.Ayers
f52a1bd37c doc: JSON-RPC 2022-08-26 20:49:57 -07:00
E.W.Ayers
4ea4365354 doc: various String docstrings 2022-08-26 20:49:57 -07:00
E.W.Ayers
3aeb3db3b5 doc: Char/Basic.lean 2022-08-26 20:49:57 -07:00
E.W.Ayers
5611620d3a dov: explanation of why pointers aren't sound. 2022-08-26 20:49:57 -07:00
E.W.Ayers
152d441a4c doc: note that Float.beq is not refl 2022-08-26 20:49:57 -07:00
Leonardo de Moura
969dce70db perf: improve FVarSubst apply functions in the new compiler stack 2022-08-26 20:10:36 -07:00
Mario Carneiro
d875f43b52 chore: remove outdated TODO 2022-08-26 15:31:13 -07:00
Mario Carneiro
ee22e637cd fix: use withContext at ac_rfl 2022-08-26 15:23:24 -07:00
E.W.Ayers
ff792c3a3a feat: abstract visitLet, visitLambda, visitForall 2022-08-25 19:09:16 -07:00
E.W.Ayers
d18667c484 feat: generalise forEachExpr
Lean.Meta.forEachExpr should be general over monads rather than restricted to the MetaM monad.
This is similar to the generalisation of Lean.Meta.transform
2022-08-25 19:09:16 -07:00
Sebastian Ullrich
e81ba951c6 fix: Core.transform API and uses 2022-08-25 19:07:42 -07:00
Fynn Schmitt-Ulms
064ab16791 feat: Float.abs function (#1514) 2022-08-25 18:45:46 -07:00
Leonardo de Moura
65f9344f01 feat: check whether join points are fully applied at Check.lean 2022-08-25 18:17:54 -07:00
Leonardo de Moura
14944aeb3c chore: print decl size at trace message 2022-08-25 18:11:49 -07:00
Leonardo de Moura
4c9c2d2bf7 feat: new CSE.lean 2022-08-25 18:08:22 -07:00
Leonardo de Moura
98575b4250 feat: new PullLetDecls.lean 2022-08-25 13:39:15 -07:00
pcpthm
bc9c14a080 fix: remove duplicate OfNat Int instance 2022-08-25 11:57:13 -07:00
Gabriel Ebner
90f92c3a9e fix: use delabAppExplicit for tooltips 2022-08-25 18:38:21 +02:00
Gabriel Ebner
a6a913495d feat: make (_ : a = b) hoverable in infoview 2022-08-25 18:38:21 +02:00
Gabriel Ebner
82e9f09bca fix: remove incorrect syntax coercion 2022-08-25 17:54:26 +02:00
Richard Musiol
d4799eaf3a doc: fix typo 2022-08-24 21:59:15 -07:00
Gabriel Ebner
8fc3bae47c chore: remove unexpanded coercion support from pp.analyze 2022-08-24 21:58:13 -07:00
Leonardo de Moura
3b4862e1a7 feat: add LCNF/DependsOn.lean 2022-08-24 21:56:10 -07:00
Leonardo de Moura
4e8b4e96e9 feat: simplify LCtx 2022-08-24 14:16:26 -07:00
Leonardo de Moura
85866fc238 chore: fix and disable some LCNF tests
We still need to port code to the new architecture
2022-08-24 14:12:27 -07:00
Leonardo de Moura
9b28878615 fix: AltCore.inferType 2022-08-24 14:05:25 -07:00
Leonardo de Moura
8102e1e31b fix: jp case at check 2022-08-24 11:50:00 -07:00
Leonardo de Moura
3a2758a59b refactor: new LCNF frontend 2022-08-24 11:40:37 -07:00
Leonardo de Moura
cabcadf9cc feat: add ppDecl 2022-08-24 08:41:45 -07:00
Leonardo de Moura
f2f3a72196 feat: add ToDecl.lean 2022-08-24 08:31:38 -07:00
Leonardo de Moura
6e068bebd1 feat: LCNF pretty printer 2022-08-24 08:16:00 -07:00
Leonardo de Moura
54e4cfa8e2 chore: doc string 2022-08-24 06:55:51 -07:00
Leonardo de Moura
083523ee9c feat: att new LCNF/toLCNF.lean 2022-08-23 20:21:06 -07:00
Leonardo de Moura
3e2f8c61ec feat: helper LCNF functions 2022-08-23 19:37:33 -07:00
Leonardo de Moura
cd49e564cf chore: add LCNF/Util.lean 2022-08-23 19:35:11 -07:00
Leonardo de Moura
f5415b2f81 feat: add Decl.check 2022-08-23 13:11:42 -07:00
Leonardo de Moura
bce7eadfbc feat: add LCNF/Check.lean 2022-08-23 08:50:59 -07:00
Leonardo de Moura
766afdd0bc feat: store FunDecls at LCNF local context 2022-08-22 21:46:37 -07:00
Leonardo de Moura
82acc2b39c feat: improve Code.bind
Add `joinTypes`.
2022-08-22 21:07:36 -07:00
Leonardo de Moura
1f57155eb9 feat: add Code.bind concatenating LCNF code blocks 2022-08-22 20:17:52 -07:00
Leonardo de Moura
a2fabc6d49 feat: inferType for new LCNF 2022-08-22 19:51:17 -07:00
Leonardo de Moura
bd1186536f feat: LCNF to Expr translator 2022-08-22 17:59:27 -07:00
Leonardo de Moura
b2c2d49bae feat: new CompilerM for LCNF 2022-08-22 17:52:04 -07:00
Leonardo de Moura
92d157f705 feat: local context for LCNF 2022-08-22 16:57:12 -07:00
Leonardo de Moura
e1ae11a708 refactor: copy LCNFTypes.lean to LCNF/Types.lean
The old file is going to be deleted after we complete the refactor.
2022-08-22 16:56:15 -07:00
Leonardo de Moura
9ed83e23ae feat: dead code eliminator for the new LCNF structure 2022-08-22 16:30:37 -07:00
Leonardo de Moura
18f3af302b feat: new datastructure for representing LCNF code 2022-08-22 16:25:11 -07:00
Leonardo de Moura
f8c7de5a64 feat: add new performance counters 2022-08-21 19:48:30 -07:00
Leonardo de Moura
bc5b6272d8 fix: use _mustInline in lambdas only 2022-08-21 16:41:18 -07:00
Leonardo de Moura
d11947abc0 perf: optimize mkLetUsingScope
Avoid overhead of `hasLooseBVars` at `LocalContext.mkBinding`
2022-08-21 16:07:29 -07:00
Leonardo de Moura
eaa384bd81 perf: remove unnecessary calls to ensureUniqueLetVarNames
`instantiateRevInternalize` is already ensuring we have unique names.
2022-08-21 14:15:42 -07:00
Leonardo de Moura
84204432db chore: fix test output 2022-08-21 14:01:18 -07:00
Leonardo de Moura
9700b58114 fix: mustInline at Compiler.simp 2022-08-21 13:57:56 -07:00
Leonardo de Moura
df89717ae3 perf: custom isTypeFormerType for toLCNF translation 2022-08-21 12:45:37 -07:00
Leonardo de Moura
cae7b7443d chore: remove trace leftovers 2022-08-21 11:42:50 -07:00
Leonardo de Moura
7c0bb0a6dc feat: add compiler.check option 2022-08-21 11:15:07 -07:00
Leonardo de Moura
faabf14c1b perf: improve PullLocalDecls.dependsOn 2022-08-21 11:15:07 -07:00
Andrés Goens
fa22507e8e feat: blocking behavior on EOF for getLine (#1479) 2022-08-21 16:27:48 +02:00
Sebastian Ullrich
221c239600 fix: alternative tar fix 2022-08-21 16:15:03 +02:00
Leonardo de Moura
778f9aa08f feat: eta expand local function declarations that are not being inlined 2022-08-21 06:38:42 -07:00
Leonardo de Moura
fa7769260a perf: combine instantiateRev and internalize in a single traversal 2022-08-20 20:03:05 -07:00
Leonardo de Moura
b2a99e1b68 chore: minor optimization at mkFlatLet 2022-08-20 20:03:05 -07:00
Leonardo de Moura
776a9b0dcb feat: don't eagerly simplify local functions that will be inlined 2022-08-20 20:03:05 -07:00
Leonardo de Moura
571a839416 chore: doc strings and add .mustInline case 2022-08-20 20:03:05 -07:00
Leonardo de Moura
d2d0a745d5 feat: use eta-reduction when reducing projection instances 2022-08-20 20:03:05 -07:00
Leonardo de Moura
a5034d6700 feat: add performance counter to Compiler.Simp 2022-08-20 20:03:05 -07:00
Sebastian Ullrich
7ce3a413e4 fix: CI: create portable tarballs 2022-08-21 00:04:24 +02:00
Sebastian Ullrich
5ce5576b5d fix: hygienic resolution of namespaces 2022-08-20 22:29:46 +02:00
Sebastian Ullrich
6f0faa8000 chore: update stage0 2022-08-20 22:29:46 +02:00
Sebastian Ullrich
5694dea36d chore: prepare bootstrap change 2022-08-20 22:29:46 +02:00
Leonardo de Moura
3788145a56 perf: minimize instantiateRev number of calls 2022-08-20 08:36:27 -07:00
Leonardo de Moura
6c1e9d9b28 perf: use [specialize] at withNewScope 2022-08-19 18:56:15 -07:00
Leonardo de Moura
36cca3ebdd perf: add toLCNFType cache 2022-08-19 18:49:33 -07:00
Leonardo de Moura
b37178d547 perf: improve toLCNFType 2022-08-19 18:40:44 -07:00
Leonardo de Moura
879a466875 perf: improve isTypeFormerType 2022-08-19 18:23:28 -07:00
Henrik Böving
d0aa234c78 feat: handle out of scope join points in join point finder 2022-08-19 17:44:54 -07:00
Henrik Böving
743ce431dc feat: HashSet.forM 2022-08-19 17:44:54 -07:00
Leonardo de Moura
8aa9d2cdbf feat: add "cases on cases" simplification 2022-08-19 17:39:10 -07:00
Leonardo de Moura
49823c28c4 fix: inlining heuristic 2022-08-19 16:23:37 -07:00
Leonardo de Moura
15f0e26368 feat: replace cases alternative with unreachable if one of the fields is the empty type 2022-08-19 12:25:46 -07:00
Leonardo de Moura
a29a61b728 chore: remove dead code 2022-08-19 11:56:22 -07:00
Leonardo de Moura
a7c96142ea feat: improve code inliner
and fix bugs at the `onlyOneExitPoint` case.
2022-08-19 11:33:34 -07:00
Leonardo de Moura
6d11dc9b62 feat: add mkAuxDeclName 2022-08-19 11:31:56 -07:00
Leonardo de Moura
b1e292e238 feat: add option for disabling join point scope checking 2022-08-19 11:31:18 -07:00
Leonardo de Moura
d0c8ad1d22 feat: reduce number of simp steps 2022-08-19 05:54:50 -07:00
Leonardo de Moura
88c4d5c340 perf: simplify and optimize inlineProjInst? 2022-08-19 04:49:31 -07:00
Leonardo de Moura
4cbe67954b feat: improve inlineProjInst? 2022-08-18 18:25:55 -07:00
Leonardo de Moura
9a04193e73 fix: getStage1Decl? minor issue 2022-08-18 17:40:05 -07:00
Leonardo de Moura
0b2d013beb chore: remove leftover 2022-08-18 17:39:29 -07:00
Leonardo de Moura
9ae2b83ac0 feat: add Compiler.Decl.pullInstances 2022-08-18 15:09:22 -07:00
Leonardo de Moura
bf2c0bf5b7 feat: avoid generation of auxliary join points when inlining functions that have only one exit point 2022-08-18 00:12:24 -07:00
Leonardo de Moura
23be59b747 chore: add Compiler.stat trace option 2022-08-18 00:10:56 -07:00
Leonardo de Moura
c780d390d6 fix: bug at InferType.lean 2022-08-18 00:10:35 -07:00
Leonardo de Moura
651d4044b3 fix: bug at attachJp 2022-08-17 19:22:53 -07:00
Leonardo de Moura
8985a15f96 chore: mark inferInstance and inferInstanceAs as [inline]
New code generator does not inline simple declarations not tagged with
`[inline]` yet. We need this change to simpilify testing
2022-08-17 19:08:51 -07:00
Leonardo de Moura
ff53e9cc56 chore: remove leftover 2022-08-17 19:04:12 -07:00
Leonardo de Moura
3a898802f7 feat: inline type class instances 2022-08-17 19:01:49 -07:00
Leonardo de Moura
6561fc259f feat: add MonadBacktrack instance for CompilerM 2022-08-17 18:51:26 -07:00
Leonardo de Moura
861bcee6a9 feat: add simpAppApp? 2022-08-17 17:57:49 -07:00
Leonardo de Moura
546179fd7e chore: add Compiler.simp.step trace option 2022-08-17 17:41:44 -07:00
Leonardo de Moura
275feed318 feat: simplify projection of constructor 2022-08-17 17:16:30 -07:00
Leonardo de Moura
18c95e8322 fix: bug at toLCNF cache 2022-08-17 17:16:13 -07:00
Leonardo de Moura
d7acf1f844 feat: add Compiler.jp trace class 2022-08-17 16:22:09 -07:00
Leonardo de Moura
f0791559b8 chore: fix test
Ensure `targetUri`s in the test output do not contain full paths on my machine.
2022-08-17 15:24:00 -07:00
Leonardo de Moura
26b417acf8 chore: update stage0 2022-08-17 15:12:04 -07:00
Mario Carneiro
20f9b7172f doc: documentation for Init.SizeOf 2022-08-17 14:48:10 -07:00
Mario Carneiro
8182f83929 doc: documentation for Init.Tactics 2022-08-17 14:44:40 -07:00
Henrik Böving
70ef3875d1 feat: add join point detector 2022-08-17 14:38:46 -07:00
Leonardo de Moura
ea35f6e091 fix: missing mkJpDeclIfNotSimple 2022-08-17 14:35:07 -07:00
Leonardo de Moura
31f7c51d14 feat: add simp loop
Keeps simplifying while making progress.
2022-08-17 11:57:33 -07:00
Leonardo de Moura
2820958f64 doc: attachJp 2022-08-17 11:14:56 -07:00
Leonardo de Moura
1d936e2d6b feat: sanity checking at attachJp 2022-08-17 09:47:59 -07:00
Leonardo de Moura
f0370749f9 feat: check whether there are jumps to out of scope join points
In a local function declaration, we can only jump to local join
points.
2022-08-17 09:38:19 -07:00
Leonardo de Moura
320a5a708c fix: avoid out-of-scope jumps at CSE 2022-08-17 09:06:00 -07:00
Leonardo de Moura
0d52a3f92b fix: add attachJp
Auxiliary function for attaching jump to a join point to an existing
let-code block.
2022-08-17 07:32:11 -07:00
Leonardo de Moura
763cf31c3b test: go to definition 2022-08-17 06:05:00 -07:00
E.W.Ayers
81ad807bb3 test: more unit tests
Some taken from https://stackoverflow.com/questions/37172819/test-if-c98-string-is-a-number-in-scientific-notation
2022-08-17 05:57:22 -07:00
E.W.Ayers
4e7c1e1ec8 fix: missing digits in scientific literal should be an error 2022-08-17 05:57:22 -07:00
Mario Carneiro
ba938d4a6e doc: documentation for Init.Notation 2022-08-17 05:56:10 -07:00
Mario Carneiro
37a12b635b feat: add declId hover for syntax/notation/mixfix 2022-08-17 05:55:06 -07:00
Leonardo de Moura
fd11e662b0 chore: update stage0 2022-08-16 18:36:39 -07:00
Mario Carneiro
e0221db2e2 feat: add @[inheritDoc] attribute 2022-08-16 18:31:55 -07:00
Leonardo de Moura
600740da85 feat: inlining local function declarations 2022-08-16 18:23:49 -07:00
Leonardo de Moura
aac711cf92 feat: inlining statistics 2022-08-16 18:23:49 -07:00
Leonardo de Moura
2f57a0e6d5 refactor: cleaup compiler simplifier 2022-08-16 18:23:49 -07:00
Leonardo de Moura
9f46996db7 feat: inliner 2022-08-16 18:23:49 -07:00
Leonardo de Moura
0e3e1353e2 feat: new Compiler trace classes 2022-08-16 18:23:49 -07:00
Leonardo de Moura
e8fdfe4193 feat: eliminate trivial let-declarations 2022-08-16 18:23:49 -07:00
Leonardo de Moura
117db0da01 feat: add Compiler/Simp.lean 2022-08-16 18:23:49 -07:00
Leonardo de Moura
daa833d5c9 feat: preserve internal let-declaration binder names 2022-08-16 18:23:49 -07:00
Leonardo de Moura
e876d81692 fix: missing withRoot true 2022-08-16 18:23:49 -07:00
E.W.Ayers
d543867241 doc: fix typos 2022-08-16 08:31:58 -07:00
E.W.Ayers
ff5b02622c doc: Format 2022-08-16 08:31:58 -07:00
E.W.Ayers
2e99e8c22d feat: Float ↔ Json 2022-08-16 08:01:23 -07:00
E.W.Ayers
9e194e3c3d fix: add + parser to decimalNumberFn 2022-08-16 07:29:39 -07:00
E.W.Ayers
a763d9d81e fix: decodeScientificLitVal? parses 1.0e+1 correctly
fixes #1484
2022-08-16 07:29:39 -07:00
Leonardo de Moura
37ba0df584 feat: do not generate code for matcher auxiliary declarations
We are macro inlining them.
2022-08-15 20:10:33 -07:00
Leonardo de Moura
7979d03386 fix: bug at CSE.lean 2022-08-15 20:04:29 -07:00
Leonardo de Moura
327442a85c feat: add mkFreshBinderName and use it to normalize internal names 2022-08-15 19:47:37 -07:00
Leonardo de Moura
caf2bb0797 feat: inline auxiliary matcher applications 2022-08-15 19:47:05 -07:00
Leonardo de Moura
7ca3535820 refactor: add mkJump 2022-08-15 18:39:27 -07:00
Leonardo de Moura
d0203ca1dc feat: add Decl.ensureUniqueLetVarNames 2022-08-15 13:03:07 -07:00
Leonardo de Moura
142b9bec36 feat: add ensureUniqueLetVarNames 2022-08-15 12:59:36 -07:00
Leonardo de Moura
e931c6b5b5 fix: bug at toLCNF 2022-08-15 12:59:36 -07:00
Patrick Massot
c9ccc9c253 doc: some SimplePersistentEnvExtension methods
See discussion at https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/Persistent.20extension.20not.20persisting
2022-08-15 12:09:00 -07:00
Leonardo de Moura
4f79d2caa0 feat: improve toLCNF
Preserve type formers only if they are application arguments
2022-08-15 09:53:48 -07:00
Gabriel Ebner
2e6395d525 doc: trace messages 2022-08-15 08:55:25 -07:00
Gabriel Ebner
e96afa28fe chore: use named emoji 2022-08-15 08:55:25 -07:00
Gabriel Ebner
e4a7b82c8d feat: use interactive goals in messages 2022-08-15 08:55:25 -07:00
Gabriel Ebner
34b0b4b7e2 chore: fix tests 2022-08-15 08:55:25 -07:00
Gabriel Ebner
5e4b30c777 chore: remove traceCtx 2022-08-15 08:55:25 -07:00
Gabriel Ebner
0e8c05134f chore: improve pp.analyze traces 2022-08-15 08:55:25 -07:00
Gabriel Ebner
b38e55bac3 chore: mark simp trace classes as inherited 2022-08-15 08:55:25 -07:00
Gabriel Ebner
d5eb9f3400 chore: improve check traces 2022-08-15 08:55:25 -07:00
Gabriel Ebner
13b5586b26 chore: improve appbuilder traces 2022-08-15 08:55:25 -07:00
Gabriel Ebner
aa2be22df7 fix: group trace messages into one diagnostic 2022-08-15 08:55:25 -07:00
Gabriel Ebner
64031e5231 chore: remove obsolete addTraceOptions 2022-08-15 08:55:25 -07:00
Gabriel Ebner
4e2899e354 chore: remove nested trace api 2022-08-15 08:55:25 -07:00
Gabriel Ebner
3a9152f007 chore: improve defeq traces 2022-08-15 08:55:25 -07:00
Gabriel Ebner
f89f6cb56c chore: improve elab traces 2022-08-15 08:55:25 -07:00
Gabriel Ebner
278724786a chore: improve tc synth traces 2022-08-15 08:55:25 -07:00
Gabriel Ebner
ef223c02b8 feat: make trace class inheritance opt-in 2022-08-15 08:55:25 -07:00
Gabriel Ebner
847125d2e8 chore: remove global trace enabled flag 2022-08-15 08:55:25 -07:00
Gabriel Ebner
96034d15b6 chore: remove obsolete trace functions 2022-08-15 08:55:25 -07:00
Gabriel Ebner
7e020d45e6 feat: add emoji helpers for trace messages 2022-08-15 08:55:25 -07:00
Gabriel Ebner
c7e45722a3 feat: trace nodes with messages 2022-08-15 08:55:25 -07:00
Leonardo de Moura
a3e1b696fb chore: update stage0 2022-08-15 08:43:33 -07:00
Mario Carneiro
a4f1db7aca feat: attributes on {macro,elab}(_rules) 2022-08-15 08:40:40 -07:00
Leonardo de Moura
a23567065d chore: update stage0 2022-08-15 06:26:40 -07:00
Leonardo de Moura
bf7b105b74 chore: remove workaround 2022-08-15 06:26:04 -07:00
Leonardo de Moura
ef308e7f2c chore: remove leftover notation 2022-08-15 06:25:35 -07:00
Leonardo de Moura
09c0f43ce5 chore: update stage0 2022-08-15 06:22:47 -07:00
Leonardo de Moura
d903d85a53 chore: prepare to remove have notation leftover 2022-08-15 06:21:23 -07:00
Leonardo de Moura
9bafe2f5b5 chore: update stage0 2022-08-14 11:20:54 -07:00
Mario Carneiro
3b793b949b feat: attributes on notation 2022-08-14 11:18:20 -07:00
Leonardo de Moura
126ad49401 feat: add stage1 extension for storing LCNF declarations 2022-08-14 10:59:36 -07:00
Henrik Böving
afbe296edb doc: doc-strings for CompilerM 2022-08-14 09:33:58 -07:00
Henrik Böving
8e29fa88eb fix: address code review for jp checker 2022-08-14 09:33:58 -07:00
Henrik Böving
ff9c9032b4 feat: join point validator 2022-08-14 09:33:58 -07:00
Leonardo de Moura
ed616abfb3 fix: hover information and go-to definition for notation defined using binop% 2022-08-13 21:34:27 -07:00
Mario Carneiro
b3ba6d4bf7 fix: use resolveGlobalConstNoOverloadWithInfo more 2022-08-13 18:20:55 -07:00
Leonardo de Moura
7a8c91fe83 chore: update stage0 2022-08-13 18:15:14 -07:00
Leonardo de Moura
713108b7ba chore: re-enable warningAsError 2022-08-13 18:07:30 -07:00
Leonardo de Moura
1e1c231edd chore: update stage0 2022-08-13 18:07:30 -07:00
Leonardo de Moura
d87d0f47a6 chore: temporarily disable warningAsError 2022-08-13 18:07:30 -07:00
Sebastian Ullrich
a2d59b9c93 fix: preserve condition position info in if 2022-08-13 18:07:30 -07:00
Sebastian Ullrich
81c744b12f chore: update tests 2022-08-13 18:07:30 -07:00
Sebastian Ullrich
f117606728 fix: replace uses of token antiquotations for setting position ranges with withRef 2022-08-13 18:07:30 -07:00
Sebastian Ullrich
ed754725e6 fix: discriminant info tree term 2022-08-13 18:07:30 -07:00
Sebastian Ullrich
757da9f6f3 fix: more accurate invalid shadowin error position 2022-08-13 18:07:30 -07:00
Sebastian Ullrich
a91ad198b2 fix: set ref in expandMacros like with regular expansion 2022-08-13 18:07:30 -07:00
Leonardo de Moura
56ee71fa0b chore: update stage0 2022-08-13 18:07:30 -07:00
Sebastian Ullrich
b97a145836 fix: annotate all syntax nodes produced by quotations as synthetic 2022-08-13 18:07:30 -07:00
Mario Carneiro
b201db4bf7 feat: add hover info for quot precheck 2022-08-13 17:31:57 -07:00
Leonardo de Moura
5f01746dba chore: update stage0 2022-08-13 17:24:58 -07:00
Mario Carneiro
c961cd1310 feat: doc comments on notation 2022-08-13 17:18:14 -07:00
Mario Carneiro
014db5d6d0 doc: relocate doc strings from elab to syntax 2022-08-13 17:16:40 -07:00
Mario Carneiro
b0db7deeef doc: documentation for Init.Coe 2022-08-13 17:15:49 -07:00
Henrik Böving
0d27c5c5cd doc: doc-strings for the entrypoints of the compiler 2022-08-13 17:11:07 -07:00
Leonardo de Moura
745f77c657 chore: let x := lcUnreachable .. should not occur in LCNF 2022-08-13 16:24:44 -07:00
Leonardo de Moura
6c5638d85b fix: bug at toLCNF 2022-08-13 15:22:22 -07:00
Leonardo de Moura
7b440040f8 test: add Gabriel's examples
They expose issues in the current code generator
2022-08-13 11:51:09 -07:00
Leonardo de Moura
cba5f1b374 test: add examples that produce the LCNF "any" type 2022-08-13 11:37:35 -07:00
Leonardo de Moura
996968c54c chore: display LCNF declaration type at Compiler.step 2022-08-13 11:35:46 -07:00
Leonardo de Moura
d2c0aa4d6d chore: remove dead code 2022-08-13 11:24:51 -07:00
Leonardo de Moura
9b1db198af fix: bug at toLCNF 2022-08-13 10:30:12 -07:00
Leonardo de Moura
212456720c fix: bug at TerminalCases
`Context.jp?` is not a continuation for the local lambda.
2022-08-13 10:15:43 -07:00
Leonardo de Moura
d439160f31 fix: missing cases at compatibleTypes 2022-08-13 10:03:14 -07:00
Leonardo de Moura
0a423b3699 fix: ensure the the terminal expression in let-declaration block is not a lambda 2022-08-13 09:47:59 -07:00
Leonardo de Moura
a17d00867f feat: common subexpression elimination 2022-08-12 16:52:18 -07:00
Leonardo de Moura
dc69a20893 feat: add mapValue 2022-08-12 16:38:20 -07:00
Leonardo de Moura
0b585d6f3d fix: bug at Compiler/Check.lean 2022-08-12 13:59:56 -07:00
Mario Carneiro
9de477ecf9 feat: add more float functions 2022-08-12 13:12:59 -07:00
Chris Lovett
50cd7debe1 feat: simple uri escaping and unescaping (#1452) 2022-08-12 19:56:05 +00:00
Leonardo de Moura
37057fdd31 feat: eagerly inline simple join points 2022-08-12 11:15:12 -07:00
Leonardo de Moura
84d9c6ed8b fix: bug at TerminalCases.lean 2022-08-12 10:59:15 -07:00
Leonardo de Moura
cfbefd993b fix: lambdaBoundedTelescope at Compiler/Check.lean 2022-08-12 10:20:54 -07:00
Mario Carneiro
6906a4d1ee feat: generalize ReaderT definitions 2022-08-12 08:23:11 -07:00
Mario Carneiro
94f85ae649 fix: don't show NaN sign info in Float.toString 2022-08-12 08:21:47 -07:00
Mario Carneiro
0738136446 feat: add lineEq parser alias 2022-08-12 08:15:28 -07:00
Mario Carneiro
1302d8f7fc feat: prefer syntax doc over elab when both are present
closes #1443
2022-08-12 08:14:55 -07:00
Mario Carneiro
311d376bde doc: typos and indentation 2022-08-12 08:14:20 -07:00
Sebastian Ullrich
d1beded289 chore: Nix: sanitize drv names 2022-08-12 15:30:22 +02:00
Wojciech Nawrocki
98571e6620 doc: explain acronym 2022-08-12 10:28:49 +02:00
Leonardo de Moura
104196e599 feat: add profileitM to compiler new entry point 2022-08-11 19:04:33 -07:00
Leonardo de Moura
e04453a89e chore: improve getMaxLetVarIdx 2022-08-11 19:01:41 -07:00
Leonardo de Moura
6d5272a404 fix: new compiler type checker 2022-08-11 18:57:06 -07:00
Leonardo de Moura
2eab711308 chore: add trace.Compiler.step 2022-08-11 18:40:13 -07:00
Leonardo de Moura
77735e62f5 chore: remove leftovers 2022-08-11 18:40:13 -07:00
Leonardo de Moura
623e0e9af9 feat: TerminalCases for new LCNF 2022-08-11 18:40:13 -07:00
Leonardo de Moura
073e72181d fix: bug at Compiler.inferType
Check whether declaration type mismatch at `Compiler.Decl.check`
2022-08-11 18:40:13 -07:00
Leonardo de Moura
5dbb907b56 feat: new toLCNF 2022-08-11 18:40:13 -07:00
Leonardo de Moura
6a67c13044 feat: generalize helper functions 2022-08-11 18:40:13 -07:00
Leonardo de Moura
4361eef907 fix: improve compatibleTypes and Compiler.check 2022-08-11 18:40:13 -07:00
Leonardo de Moura
3d79581f6b feat: basic LCNF conversion 2022-08-11 18:40:13 -07:00
Mario Carneiro
d8c6c827fe fix: use saturating casts in lean_float_to_uint8 to avoid UB 2022-08-11 13:30:22 -07:00
E.W.Ayers
9ac4cf927d test: add negative number case 2022-08-11 13:27:37 -07:00
Wojciech Nawrocki
42fec60b01 fix: printing of integral JsonNumbers 2022-08-11 13:27:37 -07:00
Mario Carneiro
7cc8f7c4c4 feat: go to definition for antiquot kinds 2022-08-11 17:46:36 +02:00
pcpthm
cbe9adbe9e fix: ac_rfl in subgoal
Closes #1202
2022-08-11 07:16:38 -07:00
Leonardo de Moura
dda1fd27c4 chore: fix test 2022-08-10 20:31:48 -07:00
Leonardo de Moura
109be66092 chore: fix build 2022-08-10 20:29:39 -07:00
Leonardo de Moura
e67a43ab01 refactor: disable old LCNF and TerminalCases
TODO: finish porting them to the new format.
2022-08-10 20:25:59 -07:00
Leonardo de Moura
66eb47d21a feat: type checker for LCNF 2022-08-10 20:22:38 -07:00
Leonardo de Moura
52f3a3ff2c refactor: move mkArrow to CoreM 2022-08-10 20:21:42 -07:00
Leonardo de Moura
d61b8fc68d test: for LCNF types 2022-08-10 11:07:13 -07:00
Leonardo de Moura
646b2d3b83 feat: add Lean.Compiler.compatibleTypes 2022-08-10 10:30:24 -07:00
Gabriel Ebner
e9545a426f refactor: RpcEncodable 2022-08-10 06:31:46 -07:00
Gabriel Ebner
f9a73cff9c chore: update stage0 2022-08-10 06:31:46 -07:00
Gabriel Ebner
37547ed887 feat: RpcEncodable derive handler 2022-08-10 06:31:46 -07:00
Gabriel Ebner
067f8e6449 feat: Std.TypeName and Std.Dynamic 2022-08-10 06:31:46 -07:00
Mario Carneiro
0c3383c0b0 feat: support let mut x := e | alt 2022-08-10 06:29:49 -07:00
Mario Carneiro
e51d892fc2 feat: implement USize.toUInt64 model 2022-08-09 18:04:05 -07:00
Leonardo de Moura
18ccc01cf1 feat: add inferType for LCNF 2022-08-09 17:33:24 -07:00
Leonardo de Moura
9e00cbd6d8 feat: add LCNFTypes.lean 2022-08-09 15:47:58 -07:00
Mario Carneiro
a28c19c161 doc: improve typeclass ops documentation 2022-08-09 14:25:44 -07:00
Mario Carneiro
6026894f9f doc: finish Init.Prelude docs 2022-08-09 14:25:44 -07:00
Sebastian Ullrich
185829d089 chore: update mdBook
Resolves #1421
2022-08-09 22:19:40 +02:00
Leonardo de Moura
fbb858a32c chore: missing case 2022-08-08 23:40:44 -07:00
Leonardo de Moura
1952633a75 chore: compiler simple type experiment 2022-08-08 20:18:46 -07:00
Leonardo de Moura
860d726d72 chore: update stage0 2022-08-08 05:16:14 -07:00
Leonardo de Moura
0204c5f9b7 chore: remove dead code 2022-08-07 22:13:34 -07:00
Leonardo de Moura
3c6c395e44 feat: add TerminalCases.lean 2022-08-07 22:05:19 -07:00
Leonardo de Moura
7359f95088 refactor: treat casesOn and matcher applications uniformly 2022-08-07 18:04:38 -07:00
Leonardo de Moura
c16bec6e30 refactor: move auxiliary let declaration support to CompilerM.lean 2022-08-07 17:27:40 -07:00
Leonardo de Moura
578adcd7f0 chore: release date for m5 2022-08-07 09:51:35 -07:00
Leonardo de Moura
7dbfaf9b75 fix: bug at mkSizeOfSpecLemmaInstance
closes #1441
2022-08-07 09:24:18 -07:00
Mario Carneiro
0b92f625ae feat: MissingDocs doesn't lint on struct redecl 2022-08-07 08:48:42 -07:00
Leonardo de Moura
413db56b89 refactor: simplify runTermElabM and liftTermElabM 2022-08-07 07:35:02 -07:00
Leonardo de Moura
e236eeba87 doc: liftTermElabM and runTermElabM 2022-08-07 07:13:06 -07:00
Sebastian Ullrich
4a0917e97a chore: update stage0 2022-08-07 15:13:34 +02:00
Sebastian Ullrich
d7e14ba47f feat: openDecl antiquotation 2022-08-07 15:11:07 +02:00
Leonardo de Moura
ee70805c35 feat: add LCNF missing cases 2022-08-06 20:23:29 -07:00
Leonardo de Moura
1d9075db0b chore: add more helper axioms for code generator 2022-08-06 20:20:50 -07:00
Leonardo de Moura
f9f074dbf5 chore: remove dead code 2022-08-06 20:20:50 -07:00
Leonardo de Moura
c5b5a1c6f9 chore: generate auxiliary variable names manually at LCNF.lean 2022-08-06 20:20:50 -07:00
Wojciech Nawrocki
7b7e2f54da fix: image paths 2022-08-06 23:46:09 +02:00
Wojciech Nawrocki
962a4bfa78 chore: move includeStr elaborator 2022-08-06 11:54:44 -07:00
Wojciech Nawrocki
bbe11d6e20 doc: clarify widget tutorial 2022-08-06 11:54:44 -07:00
Wojciech Nawrocki
71172fd0ae fix: unused arg 2022-08-06 11:54:44 -07:00
Wojciech Nawrocki
9b595649bf hack: rm JavaScript snippet 2022-08-06 11:54:44 -07:00
Wojciech Nawrocki
9c78f6fa0e feat: make include_str a builtin 2022-08-06 11:54:44 -07:00
Wojciech Nawrocki
3bc82a7636 feat: add include_str 2022-08-06 11:54:44 -07:00
Wojciech Nawrocki
72b9ba0dc5 chore: move tutorial to examples folder 2022-08-06 11:54:44 -07:00
Wojciech Nawrocki
4e2b3b8345 doc: move widgets chapter to Lean file 2022-08-06 11:54:44 -07:00
Wojciech Nawrocki
273bc683b9 feat: widget tutorial and general RequestM lifts 2022-08-06 11:54:44 -07:00
Mario Carneiro
37d3479e7c doc: add more docs to Init.Prelude 2022-08-06 09:32:16 -07:00
Sebastian Ullrich
3ee9ab855e fix: logging of linter warnings 2022-08-06 09:25:09 -07:00
Sebastian Ullrich
1ea2f51552 fix: handle warningAsError at logAt 2022-08-06 09:25:09 -07:00
Leonardo de Moura
4167b2466a fix: improve heuristic for issue #1419
The fix #1419 generated two regressions on Mathlib.

Fixes #1435
Fixes #1436
2022-08-06 09:00:16 -07:00
Leonardo de Moura
ab5ec6be34 chore: update stage0 2022-08-06 08:08:58 -07:00
Leonardo de Moura
386b0a75bc fix: bug at lean_nat_mod
fixes at #1433
2022-08-06 08:07:25 -07:00
Leonardo de Moura
bf59ad0efc feat: add new compiler entry point function 2022-08-06 08:05:07 -07:00
Mario Carneiro
59b32da2d9 feat: go to def on parser aliases 2022-08-06 12:44:14 +02:00
Mario Carneiro
12c8845026 feat: add builtin MissingDocs handler attr 2022-08-06 10:23:53 +02:00
Mario Carneiro
3b43cff7d3 chore: update stage0 2022-08-06 10:23:53 +02:00
Mario Carneiro
ab55af01b3 feat: add builtin MissingDocs handler attr (part 1) 2022-08-06 10:23:53 +02:00
tydeu
a5e0ae7331 chore: fix test 2022-08-06 10:20:54 +02:00
tydeu
e470dad36c chore: update Lake 2022-08-06 10:20:54 +02:00
Leonardo de Moura
9a16d4afce feat: add CompilerM.lean and LCNF.lean 2022-08-05 21:14:39 -07:00
Chris Lovett
c4121e779d fix: hexDigit ('a' ≤ c ∧ c ≤ 'f') 2022-08-05 14:08:03 -07:00
Leonardo de Moura
ddeea5e14f chore: fix test output 2022-08-05 13:01:02 -07:00
Leonardo de Moura
deafc315c7 fix: make forall_congr more robust at conv intro
closes #1426
2022-08-05 12:38:49 -07:00
Mario Carneiro
83da649a24 chore: remove typedExpr 2022-08-05 11:42:36 -07:00
Leonardo de Moura
50cecdbb62 chore: add Inhabited MProd and Inhabited PProd instances
closes #1420
2022-08-05 11:21:27 -07:00
Mario Carneiro
ea0f177bf2 feat: add unused/deprecation diagnostic tags 2022-08-05 17:45:50 +02:00
Leonardo de Moura
fdaae20594 chore: remove workaround 2022-08-04 21:29:31 -07:00
Leonardo de Moura
42deb66415 chore: update stage0 2022-08-04 21:29:07 -07:00
Leonardo de Moura
7f9be4198b fix: Induction.lean after binderIdent normalization 2022-08-04 21:28:12 -07:00
Leonardo de Moura
f08000d34a chore: update stage0 2022-08-04 21:10:20 -07:00
Leonardo de Moura
55bb8e905a chore: binderIdent normalization
fixes #1411
2022-08-04 21:10:02 -07:00
Leonardo de Moura
659300597d doc: some doc strings for Prelude.lean 2022-08-04 20:55:13 -07:00
Leonardo de Moura
13518da4c7 chore: update stage0 2022-08-04 19:37:58 -07:00
Mario Carneiro
e2f706a7f7 fix: syntax match 2022-08-04 19:35:00 -07:00
Mario Carneiro
c1d2f3c5a6 feat: make MissingDocs extensible 2022-08-04 19:35:00 -07:00
Mario Carneiro
4867e726a6 chore: update stage0 2022-08-04 19:34:57 -07:00
Mario Carneiro
eef51aced2 feat: make MissingDocs extensible (part 1) 2022-08-04 19:32:17 -07:00
Leonardo de Moura
f0272d9309 feat: multiple namespaces in mutual declarations 2022-08-04 19:18:49 -07:00
Leonardo de Moura
16d6f13eed chore: fix warnings 2022-08-04 16:05:09 -07:00
Leonardo de Moura
87bb1901e2 chore: update stage0 2022-08-04 16:01:23 -07:00
Leonardo de Moura
7cb67bb123 chore: update stage0 2022-08-04 15:57:45 -07:00
Leonardo de Moura
0717bdb66d fix: fixes #1419 2022-08-04 15:44:38 -07:00
Leonardo de Moura
f295a76b69 chore: fix test output 2022-08-04 15:29:17 -07:00
Leonardo de Moura
8615c42a5d tests: projection defeq strategy 2022-08-04 15:28:22 -07:00
Leonardo de Moura
4501bdecb1 chore: naming convention 2022-08-04 15:28:22 -07:00
Sebastian Ullrich
2f0b65fad3 fix: do not show inaccessible variable in hover 2022-08-04 11:28:46 -07:00
Leonardo de Moura
a30a31b1b0 fix: findDocString? 2022-08-04 10:32:41 -07:00
Leonardo de Moura
85cda05c92 chore: improve expandParen do notation 2022-08-04 10:01:32 -07:00
Leonardo de Moura
0ec56c3367 chore: fix doc string 2022-08-04 08:45:30 -07:00
Leonardo de Moura
1008607b25 chore: cleanup annotate method at Do.lean 2022-08-04 08:44:56 -07:00
Leonardo de Moura
9e69259f83 chore: update stage0 2022-08-03 20:01:34 -07:00
Sebastian Ullrich
abde2e4606 fix: unused variables in foreign definition 2022-08-03 18:15:15 -07:00
Mario Carneiro
f5c5af1e86 doc: document all the syntax categories (#1401)
* chore: use Category declarations for builtin cats too

* doc: document all the syntax categories

* fix: fix test
2022-08-03 18:13:39 -07:00
Mario Carneiro
e816424466 chore: use Category declarations for builtin cats too (#1400) 2022-08-03 18:10:54 -07:00
Leonardo de Moura
84ff8d4a04 feat: store pending contraints during dependent pattern matching
It is a better solution for issues #1361 and #1279, and it was on the
to-do list for a while.
2022-08-03 17:45:55 -07:00
Leonardo de Moura
f2921993bb feat: add LocalContext.replaceFVarId 2022-08-03 11:21:55 -07:00
Leonardo de Moura
cc91298570 feat: add PersistentHashMap.map and PersistentHashMap.mapM 2022-08-03 11:20:17 -07:00
Leonardo de Moura
e9bcc779fe feat: add Array.mapM' 2022-08-03 11:18:19 -07:00
Leonardo de Moura
cb6ae247aa chore: remove [specialize] annotations from fold operations on PersistentHashMap
They have little impact on performance, but increase the generated code size
2022-08-03 10:38:31 -07:00
Leonardo de Moura
cbd022e4eb refactor: replaceFVarIdAtLocalDecl => LocalDecl.replaceFVarId 2022-08-03 10:32:45 -07:00
Leonardo de Moura
b4ad6fc289 chore: do not generate "redundant alternatives" message when there are missing cases 2022-08-03 08:21:09 -07:00
Leonardo de Moura
a9e7290e4b refactor: use isDefEq instead of custom unify procedure
See comment with new issue at #1361
2022-08-02 18:00:00 -07:00
Leonardo de Moura
ae5db0f563 chore: style 2022-08-02 17:44:19 -07:00
Leonardo de Moura
fbef8a32e1 feat: add support for stuck class projection function applications at getStuckMVar?
closes #1408
2022-08-02 16:01:06 -07:00
Leonardo de Moura
40226f775f chore: doc strings for ProjFns.lean 2022-08-02 15:58:56 -07:00
Leonardo de Moura
9d36f45074 chore: cleanup 2022-08-02 14:45:19 -07:00
Leonardo de Moura
2e37582f31 feat: allow users to install their own deriving hanlders for builtin classes 2022-08-02 08:29:24 -07:00
Leonardo de Moura
5df588cbbf chore: remove unnecessary annotations 2022-08-02 05:42:53 -07:00
Leonardo de Moura
dc51583233 chore: update stage0 2022-08-02 04:59:18 -07:00
Sebastian Ullrich
a44472962d fix: replace uses of token antiquotations in tactics with with_annotate_state 2022-08-02 04:54:48 -07:00
Sebastian Ullrich
8b235579e3 fix: ignore with_annotate_state for hover/go-to 2022-08-02 04:54:48 -07:00
Sebastian Ullrich
d738e8e392 chore: update stage0 2022-08-02 04:54:48 -07:00
Sebastian Ullrich
0272c30b4b fix: token antiquotations should create synthetic positions
synthetic means synthetic means synthetic
2022-08-02 04:54:48 -07:00
Leonardo de Moura
303e322255 feat: avoid [Decidable p] instance implicit parameters in congruence theorems when possible 2022-08-02 04:47:42 -07:00
Leonardo de Moura
b2f34bdedd feat: improve congr conv tactic
It has better support for proof irrelevant and `[Decidable p]` arguments
2022-08-02 04:26:34 -07:00
Leonardo de Moura
01ce4b9982 feat: use infer_instance to close remaining goals at conv block 2022-08-02 04:24:56 -07:00
Leonardo de Moura
c143631ab1 chore: missing instantiateMVars 2022-08-02 02:24:50 -07:00
Leonardo de Moura
e6d5349abb chore: unused variable 2022-08-02 02:24:50 -07:00
Leonardo de Moura
3ab26f00ea refactor: use congr tactic to implement the congr conv tactic 2022-08-02 02:24:50 -07:00
Leonardo de Moura
e79917d9a8 fix: missing instantiateMVars 2022-08-02 02:24:50 -07:00
Leonardo de Moura
4e911765eb chore: unused vars 2022-08-02 02:24:50 -07:00
Leonardo de Moura
076d40f51c feat: use implies_congr at congr tactic, and cleanup 2022-08-02 02:24:50 -07:00
Chris Lovett
272c6ebdf1 chore: CI: remove TPIL trigger
now a cronjob
2022-08-02 09:08:23 +00:00
Leonardo de Moura
99413a18ff feat: add congr tactic 2022-08-01 18:44:07 -07:00
Leonardo de Moura
cdd2a624fc fix: mkHCongr 2022-08-01 18:44:07 -07:00
Leonardo de Moura
815bc95c47 refactor: remove duplication MVarId.applyRefl => MVarId.refl
and mark `MVarId.applyRefl` as deprecated.
2022-08-01 18:44:07 -07:00
Leonardo de Moura
a5a70a0543 chore: cleanup 2022-08-01 18:44:07 -07:00
Mario Carneiro
5f39370d94 chore: rename skip conv to rfl and add no-op skip 2022-08-01 13:54:36 -07:00
Leonardo de Moura
8781203372 chore: rename misleading function
`charToHex` is an auxiliary function used at `Char.quoteCore` for
converting ASCII control characters into `\x` notation.
Its name was misleading.

Closes #1404
2022-08-01 13:21:03 -07:00
Leonardo de Moura
e39eebabd9 fix: move doc string to parser that sets the SyntaxNodeKind for the { tac } notation
see #1403

This fixes the hover for `{ tac }`
2022-08-01 13:01:37 -07:00
Leonardo de Moura
c95acef20e fix: ignore syntax nodes with nullKind at hoverableInfoAt?
It fixes one of the problems reported at #1403
2022-08-01 12:18:36 -07:00
Leonardo de Moura
2af7bf1b54 chore: fix link at src/Lean/Server/README.md
cc @digama0
2022-08-01 11:12:19 -07:00
Leonardo de Moura
5a8ee410b1 chore: remove infoTree.lean test
Motivation: it is not very useful anymore, and more importantly it
breaks all the time because it is affected by how many internal ids
are created by Lean.
2022-08-01 10:02:24 -07:00
Leonardo de Moura
0156b59ef1 chore: enforce naming convention 2022-08-01 09:58:11 -07:00
Mario Carneiro
f235cd8537 doc: document all the convs 2022-08-01 09:28:30 -07:00
Mario Carneiro
5ed3e580ef fix: allow {} as conv 2022-08-01 08:47:51 -07:00
Mario Carneiro
25aea1b723 doc: document all the tactics 2022-08-01 08:08:03 -07:00
Sebastian Ullrich
de029566d1 fix: unused variables false positive with match 2022-08-01 07:09:08 -07:00
Mario Carneiro
df85fee62c chore: rename ac_refl to ac_rfl 2022-08-01 06:53:08 -07:00
Mario Carneiro
d92948bc20 chore: prune ancient keywords 2022-08-01 13:32:56 +02:00
Wojciech Nawrocki
161ef7a67c doc: fix link 2022-08-01 13:03:54 +02:00
Mario Carneiro
114cd3e5cd doc: add ParserCategory docs 2022-08-01 11:23:09 +02:00
Mario Carneiro
ecb787529a refactor: rename ref to declName 2022-08-01 11:23:09 +02:00
Mario Carneiro
76eddb06a5 chore: update stage0 2022-08-01 11:23:09 +02:00
Mario Carneiro
711532f5c6 feat: add ref field to ParserCategory 2022-08-01 11:23:09 +02:00
Mario Carneiro
65e2b8a932 feat: track parser names by category 2022-08-01 11:23:09 +02:00
Leonardo de Moura
c76fa06816 chore: update release notes 2022-07-31 18:25:48 -07:00
Mario Carneiro
c952c69690 feat: add missingDocs linter 2022-07-31 18:18:21 -07:00
Mario Carneiro
7cefcf1f61 fix: fix test 2022-07-31 15:42:26 -07:00
Mario Carneiro
89a16daa81 feat: add TokenMap 2022-07-31 15:42:26 -07:00
Mario Carneiro
42a4f2f451 feat: ForIn instance for NameMap and PersistentHashMap 2022-07-31 15:42:26 -07:00
Sebastian Ullrich
e6c7e2dd9f chore: CI: Nix ccache permissions 2022-07-31 23:06:47 +02:00
Leonardo de Moura
8241c49e11 fix: variable binder update commands
This issue was reported by @hrmacbeth at the ICERM after-party hackton.
2022-07-31 10:08:48 -07:00
Mario Carneiro
defaa52f64 chore: update stage0 2022-07-31 16:36:54 +02:00
Sebastian Ullrich
759a7d771f fix: do not show inferred type on attribute application 2022-07-31 16:36:54 +02:00
Mario Carneiro
603b7486e3 feat: add go-to-def for simple attributes 2022-07-31 16:36:54 +02:00
Leonardo de Moura
08047a178a chore: update stage0 2022-07-31 06:04:25 -07:00
Leonardo de Moura
8a39a2dd5a chore: update stage0 2022-07-31 06:01:51 -07:00
Leonardo de Moura
37af11ae20 fix: unused match-syntax alternatives are silently ignored
closes #1371
2022-07-31 06:00:08 -07:00
Leonardo de Moura
feb71271e9 fix: remove redundant alternatives 2022-07-31 05:28:14 -07:00
Leonardo de Moura
30efb589a6 chore: update stage0 2022-07-31 04:32:07 -07:00
Leonardo de Moura
2f00d60115 feat: helper parser for issue #1371 2022-07-31 04:30:02 -07:00
Leonardo de Moura
cc032446f4 chore: style 2022-07-30 21:29:12 -07:00
Leonardo de Moura
4c1387b99b chore: typos 2022-07-30 21:26:08 -07:00
Siddharth
68e26278c7 doc: Add explanations to MetavarContext (#1331)
* doc: Add explanations to MetavarContext

The explanations were taken from Leo's talk at the ICERM
Mathlib porting hackathon.

* Update src/Lean/MetavarContext.lean

Co-authored-by: Sebastian Ullrich <sebasti@nullri.ch>

* add my understanding of what LocalInstances represents

* Update src/Lean/MetavarContext.lean

Co-authored-by: Sebastian Ullrich <sebasti@nullri.ch>

Co-authored-by: Sebastian Ullrich <sebasti@nullri.ch>
Co-authored-by: Leonardo de Moura <leonardo@microsoft.com>
2022-07-30 21:24:42 -07:00
Leonardo de Moura
a489bdb107 doc: some doc strings 2022-07-30 21:18:50 -07:00
Leonardo de Moura
ab6af0118c doc: add inductive command doc string 2022-07-30 15:15:16 -07:00
Leonardo de Moura
f7ca057fea doc: add some doc strings at Environment.lean 2022-07-30 15:05:13 -07:00
Leonardo de Moura
378f91607c chore: update stage0 2022-07-30 14:41:45 -07:00
Leonardo de Moura
a63cb24a38 feat: structure field auto-completion 2022-07-30 14:40:21 -07:00
Leonardo de Moura
75f7681a09 chore: update stage0 2022-07-30 10:21:59 -07:00
Leonardo de Moura
83ee9b1a57 feat: auto-completion for dotted identifier notation 2022-07-30 10:21:04 -07:00
Leonardo de Moura
d38fca5f4d chore: update phoas.lean
https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/PHOAS.20example/near/291433426
2022-07-30 08:44:18 -07:00
Leonardo de Moura
3dfa895bf0 feat: OfNat instance postprocessor
Closes #1389
2022-07-30 08:35:45 -07:00
Leonardo de Moura
0e0a3e1f63 chore: style 2022-07-30 08:35:45 -07:00
Mario Carneiro
323c94ef34 feat: doc comments on anonymous initialize 2022-07-30 11:20:24 +02:00
Mario Carneiro
05e42b51b3 feat: use with_decl_name% in initialize 2022-07-30 11:20:24 +02:00
Leonardo de Moura
78927542b7 chore: doc strings 2022-07-29 21:39:34 -07:00
Leonardo de Moura
ab9b2ea3b2 chore: update stage0 2022-07-29 21:25:33 -07:00
Leonardo de Moura
b2ba20e870 chore: update stage0 2022-07-29 21:25:33 -07:00
Leonardo de Moura
ec7b5c6c2a chore: remove redundant data form Expr.Data 2022-07-29 21:25:03 -07:00
Leonardo de Moura
fbc6bcff92 chore: remove unnecessary french quotes 2022-07-29 20:53:01 -07:00
Leonardo de Moura
dadab54014 chore: remove unused param 2022-07-29 20:41:38 -07:00
Leonardo de Moura
e6031925c3 fix: bug resolving names when using def _root_. 2022-07-29 19:55:02 -07:00
Leonardo de Moura
e564ae834a doc: add doc strings 2022-07-29 18:58:36 -07:00
Leonardo de Moura
1b8cda480f feat: elabAsElim eta-expand when major premises are not provided 2022-07-29 18:31:25 -07:00
Leonardo de Moura
eafd2a88ce chore: simplify Prelude.lean and Core.lean using elabAsElim 2022-07-29 18:13:56 -07:00
Leonardo de Moura
485406cc55 fix: no hover info on _ at fun _ => ... 2022-07-29 14:53:02 -07:00
Leonardo de Moura
26a565496e chore: remove dead code 2022-07-29 14:38:00 -07:00
Leonardo de Moura
239a3b9298 chore: cleanup 2022-07-29 14:38:00 -07:00
Sebastian Ullrich
2c1e6a0343 chore: update stage0 2022-07-29 21:44:57 +02:00
Mario Carneiro
9a401c852c feat: add decl_name% / with_decl_name% macros 2022-07-29 21:42:51 +02:00
Leonardo de Moura
a44ae3c0fa fix: ensure elabAsElim does not introduce detached info nodes 2022-07-29 12:27:01 -07:00
Leonardo de Moura
6b318ddde6 chore: style 2022-07-29 12:27:01 -07:00
Sebastian Ullrich
3362b38829 chore: more unused variable to-do markers 2022-07-29 19:41:12 +02:00
Sebastian Ullrich
f4de40d7dc feat: turn on warningAsError 2022-07-29 10:31:19 -07:00
Sebastian Ullrich
f1f0f60768 fix: linter warnings 2022-07-29 10:31:19 -07:00
Sebastian Ullrich
b027946496 feat: suffix linter messages with option name 2022-07-29 10:31:19 -07:00
Sebastian Ullrich
5e6b2a9460 feat: add 'suspicious unexpander patterns' linter 2022-07-29 10:31:19 -07:00
Sebastian Ullrich
e048bbc93a perf: unused variables linter: early cut-off 2022-07-29 10:31:19 -07:00
Sebastian Ullrich
2a977d8969 refactor: move unused variables linter into separate file 2022-07-29 10:31:19 -07:00
Patrick Massot
435017231d doc: add some docstrings and docstrings details 2022-07-29 10:30:43 -07:00
Sebastian Ullrich
c11bd6fa97 test: fix foreign function signatures 2022-07-29 14:10:15 +02:00
Ed Ayers
c3f58a7eab feat: add a message if Lean 4 is called with the Lean 3 extension 2022-07-29 11:08:51 +00:00
Leonardo de Moura
3e4a805b5b chore: typo 2022-07-28 20:12:20 -07:00
Leonardo de Moura
b0feb0c867 chore: update stage0 2022-07-28 20:08:39 -07:00
Leonardo de Moura
012cb13f51 feat: add [elabAsElim] elaboration strategy 2022-07-28 20:08:29 -07:00
Leonardo de Moura
163fe62ac7 chore: update release notes 2022-07-28 15:18:40 -07:00
Leonardo de Moura
a6c53cf974 fix: fixes #1380 2022-07-28 15:14:50 -07:00
Sebastian Ullrich
a2ccf8f122 feat: accept keywords as constructor names 2022-07-28 12:46:28 -07:00
Leonardo de Moura
ee6e2036dd feat: allow relations in Type at Trans
It addresses issue reported at https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/Calc.20mode/near/291214574
2022-07-28 10:13:01 -07:00
Leonardo de Moura
d0d5effcbc doc: update doc string 2022-07-28 09:48:46 -07:00
Sebastian Ullrich
556358e84c chore: Nix: better solution for filtering test output 2022-07-28 17:12:17 +02:00
Wojciech Nawrocki
e7f91d2d01 feat: forward all args to server 2022-07-28 15:58:32 +02:00
Wojciech Nawrocki
2744f94ff5 fix: forward memory and stack sizes to server 2022-07-28 15:58:32 +02:00
Leonardo de Moura
10c49d0007 fix: preserve user-facing names and BinderInfo when lifting let-rec declarations
closes #1377
2022-07-28 06:36:45 -07:00
Siddharth
a9e22a5119 doc: src/Lean/Declaration.lean (#1330)
* doc: Add explanations to MetavarContext

The explanations were taken from Leo's talk at the ICERM
Mathlib porting hackathon.

* doc: Add documentation for Declaration

This is explanations taken from Leo's talk given
at the post ICERM Mathlib porting hackathon.

* Update src/Lean/Declaration.lean

Co-authored-by: Scott Morrison <scott@tqft.net>

* Update src/Lean/Declaration.lean

Co-authored-by: Scott Morrison <scott@tqft.net>

* Update src/Lean/MetavarContext.lean

Co-authored-by: Scott Morrison <scott@tqft.net>

* fix depth comment

Co-authored-by: Scott Morrison <scott@tqft.net>
2022-07-27 19:46:11 -07:00
Leonardo de Moura
b5ad9bd4e2 chore: update stage0 2022-07-27 19:38:19 -07:00
Leonardo de Moura
6db01d8e48 perf: simpler isDefEq caching
We don't try to reuse the cache contents between different `isDefEq`
calls. Thus, we can cache more results and ignore whether the state of
the metavariable context affects them or not.

Closes #1102
2022-07-27 19:35:45 -07:00
Leonardo de Moura
654a4b0478 fix: add term info at trailing parsers 2022-07-27 18:10:46 -07:00
Leonardo de Moura
388163e023 doc: add some doc strings 2022-07-27 18:02:47 -07:00
Leonardo de Moura
6dcba78338 refactor: improve MVarId method discoverability
See issue #1346
2022-07-27 17:49:00 -07:00
Leonardo de Moura
d267b38a91 fix: disable "error to sorry" and "error recovery" at failIfSuccess
closes #1375
2022-07-27 17:09:34 -07:00
Leonardo de Moura
888dba815d chore: update stage0 2022-07-27 16:10:38 -07:00
Leonardo de Moura
49ce4408df feat: validate parametric local instances
Closes #1373
2022-07-27 16:09:56 -07:00
Leonardo de Moura
c210781af8 refactor: add doc strings, cleanup, and dotted notation friendly API
See #1346
2022-07-27 16:01:15 -07:00
Leonardo de Moura
00dd9da304 chore: update stage0 2022-07-27 13:41:21 -07:00
Leonardo de Moura
1c770ac8d7 feat: doc strings for declare_syntax_cat
see #1374
2022-07-27 13:40:08 -07:00
Leonardo de Moura
1bf53e4fc9 doc: add doc strings for let parsers 2022-07-27 10:56:44 -07:00
Leonardo de Moura
3363ee414b doc: add doc strings for declarations added by the init_quot command
See #1374
2022-07-27 10:17:03 -07:00
Leonardo de Moura
54c5436efb chore: update stage0 2022-07-27 10:00:57 -07:00
Leonardo de Moura
a7e0976ae6 chore: style 2022-07-27 09:58:52 -07:00
Leonardo de Moura
92d360353c feat: elaborate add_decl_doc 2022-07-27 09:58:49 -07:00
Leonardo de Moura
5f55422bc2 chore: update stage0 2022-07-27 09:31:53 -07:00
Leonardo de Moura
2c0de29dfd feat: add add_decl_doc command 2022-07-27 09:30:32 -07:00
Leonardo de Moura
0d43684956 chore: fix some docstrings 2022-07-27 06:46:00 -07:00
Leonardo de Moura
97a5a88ae2 doc: add doc string to simp attribute parser 2022-07-27 06:34:55 -07:00
Leonardo de Moura
c53c4413c4 feat: add doc string to user-defined simp attribute parser
see #1374
2022-07-27 06:13:10 -07:00
Leonardo de Moura
635752dd2c feat: add info node from attributes to their parsers
see #1374
2022-07-27 06:12:43 -07:00
Leonardo de Moura
ba24f7f57a chore: update stage0 2022-07-26 18:51:10 -07:00
Leonardo de Moura
ed7f502e54 feat: doc string support for register_simp_attr, register_option, register_builtin_option, declare_config_elab
see #1374
2022-07-26 18:46:23 -07:00
Leonardo de Moura
3e7d45aaba fix: improve finer-grained term infos for do blocks
see #1248

This commit adds a small hack to fix the term info for the following `do`-elements
```lean
   let (x, y) := ...
   let (x, y) ← ...
   let mut (x, y) ← ...
   let some x ← ... | ...
```
2022-07-26 18:18:05 -07:00
Leonardo de Moura
fffd61cf98 chore: update stage0 2022-07-26 17:56:49 -07:00
Leonardo de Moura
642cf0bc6d feat: add option pp.showLetValues
closes #1345
2022-07-26 17:53:34 -07:00
Leonardo de Moura
0e3f031660 fix: position information for with_annotate_term when coercions are used
see #1248
2022-07-26 16:09:45 -07:00
Leonardo de Moura
c22120371e feat: finer-grained term infos for do blocks
closes #1248
2022-07-26 15:47:37 -07:00
Leonardo de Moura
bbad6d1efe feat: add with_annotate_term 2022-07-26 15:13:28 -07:00
Leonardo de Moura
43c787d1c6 feat: synthesize implicit structure fields in the structure instance notation
closes #1305
2022-07-26 13:24:57 -07:00
Leonardo de Moura
e68e448070 fix: convert inductive type instance implicit parameters to implicit when building SizeOf instance
It is better for TC resolution since the parameter can be inferred by
typing constraints, and it addresses issue #1373
2022-07-26 12:42:47 -07:00
Leonardo de Moura
642b30ab47 feat: add withInstImplicitAsImplict 2022-07-26 12:35:30 -07:00
Leonardo de Moura
d6f0880d11 feat: add option warningAsError 2022-07-26 05:57:54 -07:00
Leonardo de Moura
385cfa6001 fix: fixes #1372 2022-07-26 05:51:02 -07:00
Leonardo de Moura
3896244c55 chore: cleanup 2022-07-25 22:39:56 -07:00
Leonardo de Moura
30199745ad chore: update stage0 2022-07-25 22:19:59 -07:00
Leonardo de Moura
90fb110cc9 refactor: improve FVarId method discoverability
See issue #1346
2022-07-25 22:18:58 -07:00
Leonardo de Moura
db7e546155 fix: Match.unify?
closes #1361
2022-07-25 20:30:01 -07:00
Leonardo de Moura
b3b2a07ed0 feat: support dotted notation and named arguments in patterns 2022-07-25 18:19:32 -07:00
Leonardo de Moura
69b7771570 fix: etaArgs and ellipsis at elabAppArgs
When `..` is used, we should not eta-expand but add `_`s.
2022-07-25 18:13:32 -07:00
Leonardo de Moura
aa267dbc9b doc: add doc-strings 2022-07-25 17:36:10 -07:00
Leonardo de Moura
c418e8d2c5 fix: use useExplicit := false when processing instance ... where ... notation fields
See new test.
2022-07-25 16:53:13 -07:00
Leonardo de Moura
c2a13da58d fix: ensure let f | ... and let rec f | ... notations behave like the top-level ones with respect to implici lambdas
closes #1360
2022-07-25 16:53:13 -07:00
Leonardo de Moura
387b6c22ee chore: document and cleanup 2022-07-25 16:53:13 -07:00
Sebastian Ullrich
da44604c1b fix: notation delaborator on over-application 2022-07-25 13:42:37 -07:00
Leonardo de Moura
40936d52bd chore: improve [deprecated] example at release notes 2022-07-25 12:32:15 -07:00
Leonardo de Moura
f83846b481 chose: update release notes 2022-07-25 12:28:23 -07:00
Leonardo de Moura
d84fc3aed7 chore: update stage0 2022-07-25 12:22:14 -07:00
Leonardo de Moura
c042e7ba58 feat: add support for "jump-to-definition" at [tactic ...], [commandElab ...] and [termElab ...] attributes
see #1350
2022-07-25 12:21:51 -07:00
Leonardo de Moura
afce57386c chore: doc strings at KeyedDeclsAttribute.lean 2022-07-25 12:20:19 -07:00
Leonardo de Moura
f19b122ab1 feat: add support for "jump-to-definition" at [implementedBy] attribute
see #1350
2022-07-25 12:06:55 -07:00
Leonardo de Moura
6fbf15043f refactor: move InfoState to CoreM
We want to be able to update `InfoState` at `AttrM` which is just an
alias for `CoreM`.
I considered defining `AttrM` as `StateRefT InfoState CoreM`, but this
is problematic because we also want to invoke `AttrM` monadic
actions from `MetaM`.

Closes #1350
2022-07-25 11:57:56 -07:00
Leonardo de Moura
c62404a97a refactor: split InfoTree.lean 2022-07-25 08:41:34 -07:00
Wojciech Nawrocki
12b3573c14 fix: tests 2022-07-25 08:01:27 -07:00
Wojciech Nawrocki
e30ae62dff refactor: simplify position type 2022-07-25 08:01:27 -07:00
E.W.Ayers
b714e087d6 fix: widgetSourceRegistry now stores the UserWidgetDefinition declaration name instead of WidgetSource
This means that the environment extension is not storing a big text object and instead the text
is retrieved from the declaration itself.
2022-07-25 08:01:27 -07:00
E.W.Ayers
591b218607 doc: fix @kha issues 2022-07-25 08:01:27 -07:00
Wojciech Nawrocki
122748ab06 test: strip some more indices 2022-07-25 08:01:27 -07:00
Wojciech Nawrocki
5183887722 test: fix infoTree.lean 2022-07-25 08:01:27 -07:00
E.W.Ayers
28ebf90948 fix: add Inhabited Std.RBMap 2022-07-25 08:01:27 -07:00
E.W.Ayers
8deee553bb fix: local instances 2022-07-25 08:01:27 -07:00
Ed Ayers
05f79def8c style: tests/lean/interactive/run.lean
Co-authored-by: Gabriel Ebner <gebner@gebner.org>
2022-07-25 08:01:27 -07:00
E.W.Ayers
c4c87ebe55 test: remove unused rpc case from runner 2022-07-25 08:01:27 -07:00
E.W.Ayers
67eae54c3d style: userwidget 2022-07-25 08:01:27 -07:00
E.W.Ayers
839956c75e doc: update widget docs
[skip ci]
2022-07-25 08:01:27 -07:00
E.W.Ayers
18a3d1a34e fix: widgets are now defined using a UserWidgetDefinition
To satisfy https://github.com/leanprover/lean4/pull/1238#discussion_r908839474
2022-07-25 08:01:27 -07:00
Wojciech Nawrocki
0824e6b22b chore: rebase on 2022-07-10 2022-07-25 08:01:27 -07:00
Wojciech Nawrocki
625be05aa8 chore: use invalidParams error code 2022-07-25 08:01:27 -07:00
E.W.Ayers
4eb97a7954 refactor: getWidgetInfos → getWidgets
also rm hash field from UserWidgetInfo because it can be computed in handler instead.
2022-07-25 08:01:27 -07:00
E.W.Ayers
9b5be5a039 chore: remove Json.syntax docstring 2022-07-25 08:01:27 -07:00
E.W.Ayers
b7d70877f7 feat: user widgets
See #1225
2022-07-25 08:01:27 -07:00
Leonardo de Moura
262ac674aa feat: improve runTactic
It must catch exceptions.
See #1342
2022-07-25 07:41:50 -07:00
Sebastian Ullrich
005b8aa951 chore: update stage0 2022-07-25 10:13:56 +02:00
Sebastian Ullrich
7272235241 fix: escaped $$x* antiquotation splices 2022-07-25 10:09:58 +02:00
Lars
105bfcc8f0 feat: allow custom ignore functions for the unused variables linter
Co-authored-by: Sebastian Ullrich <sebasti@nullri.ch>
2022-07-25 09:16:44 +02:00
tydeu
938516b00c chore: update Lake 2022-07-25 08:52:00 +02:00
Leonardo de Moura
0ec2b442d1 chore: update stage0 2022-07-24 21:38:48 -07:00
Leonardo de Moura
8335a82aed refactor: improve MVarId method discoverability
See issue #1346
2022-07-24 21:36:33 -07:00
Leonardo de Moura
91999d22eb chore: update stage0 2022-07-24 18:08:31 -07:00
Leonardo de Moura
d9d893e425 chore: fix test 2022-07-24 18:07:54 -07:00
Leonardo de Moura
b6e9d58537 feat: add [deprecated] attribute 2022-07-24 18:06:03 -07:00
Leonardo de Moura
f1f5a4b39e chore: naming convention 2022-07-24 17:44:29 -07:00
Leonardo de Moura
a62949c49b refactor: add type LevelMVarId (and abbreviation LMarId)
Motivation: make sure we do not mixup metavariable ids for
expression and universe level.

cc @bollu
2022-07-24 17:21:45 -07:00
Leonardo de Moura
949dddbf63 fix: lean_float_array_data 2022-07-24 17:05:28 -07:00
Leonardo de Moura
e0882e098b chore: avoid stackoverflow in debug build 2022-07-24 14:47:51 -07:00
Leonardo de Moura
2c825de6a1 fix: elim_scalar_array_cases 2022-07-24 14:46:46 -07:00
Leonardo de Moura
5e877b115b feat: improve calc tactic
> Heather suggested changing the calc tactic (not the term) such that if
the final RHS does not defeq match the goal RHS, it returns a final
inequality as a subgoal.

Closes #1342
2022-07-24 14:30:15 -07:00
Leonardo de Moura
fd0581f485 refactor: add Elab/Calc.lean 2022-07-24 13:30:05 -07:00
Leonardo de Moura
c46ef56ac7 perf: avoid blowup at deriving Repr
The fix is not perfect. I just avoided inlining in some builtin `Repr` instances.
The actual problem is at `ElimDeadBranches.lean`.

Closes #1365
2022-07-24 13:10:04 -07:00
Leonardo de Moura
5253cc6742 fix: compiler support for FloatArray.casesOn and ByteArray.casesOn
closes #1311
2022-07-24 12:36:08 -07:00
Leonardo de Moura
7829be9d54 fix: fixes #1333 2022-07-24 12:19:53 -07:00
Leonardo de Moura
2196a3518e perf: improve lazy_delta_reduction_step heuristic
It addresses a performance issue reported at
https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/performance.20of.20equality.20with.20projections.2Fmutual/near/288083209
2022-07-24 11:48:45 -07:00
Sebastian Ullrich
a941b1b859 chore: one more unused import 2022-07-24 18:24:25 +02:00
Leonardo de Moura
22d37af5c9 feat: improve calc syntax
See #1342
2022-07-24 08:32:20 -07:00
Leonardo de Moura
6cff1f1813 fix: try to postpone by .. if expectedType? = none
Reason: it may become `some ..` later. See issue #1359

Closes #1359
2022-07-24 08:03:25 -07:00
Leonardo de Moura
28fc2f9d37 fix: improve "{varName} cannot be reassigned" error message
closes #1341
2022-07-24 07:44:34 -07:00
Leonardo de Moura
ad5ee05a03 chore: consistent use of backticks in error messages at Do.lean 2022-07-24 07:42:04 -07:00
Leonardo de Moura
8de798c4a6 feat: reject [macroInline] declarations in recursive declarations
closes #1363
2022-07-24 07:26:35 -07:00
Sebastian Ullrich
6a767a66a1 perf: reduce Lean.Parser.Basic imports 2022-07-23 23:01:52 +02:00
Sebastian Ullrich
e5891850a7 doc: update RELEASES.md 2022-07-23 17:09:32 +02:00
Sebastian Ullrich
5160cb7b0f refactor: remove some unnecessary antiquotation kind annotations 2022-07-23 17:09:32 +02:00
Sebastian Ullrich
cf380956a3 fix: regression from previous commit 2022-07-23 17:09:32 +02:00
Sebastian Ullrich
29b7289b11 chore: update stage0 2022-07-23 17:09:32 +02:00
Sebastian Ullrich
b1a9c58d43 feat: relax eager antiquotation parsing 2022-07-23 17:09:32 +02:00
Sebastian Ullrich
9e9786203f doc: fix minted example 2022-07-23 15:14:44 +02:00
Mario Carneiro
f6211b1a74 chore: convert doc/mod comments from /- to /--//-! (#1354) 2022-07-22 12:05:31 -07:00
Sebastian Ullrich
40c1bde7f1 feat: trace for backtracked tactic exceptions 2022-07-22 11:49:50 -07:00
Sebastian Ullrich
5e9ca825d1 refactor: simplify evalTactic backtracking 2022-07-22 11:49:50 -07:00
Leonardo de Moura
8f4ad15a47 fix: ensure messages associated with last exception are not lost at evalTactic
closes #1358
2022-07-22 12:05:29 -04:00
Sebastian Ullrich
1f081ee6cb feat: doc comment support for unif_hint 2022-07-22 14:30:49 +02:00
Sebastian Ullrich
ce0a0166e8 chore: update stage0 2022-07-22 14:30:49 +02:00
Sebastian Ullrich
8e07e80f72 feat: docComment parser alias 2022-07-22 14:30:49 +02:00
Sebastian Ullrich
a10a5335ba fix: do not highlight module docstrings
Fixes #1353
2022-07-22 13:47:47 +02:00
Gabriel Ebner
4d5515ab0c fix: do not use native_decide 2022-07-22 13:06:04 +02:00
Mario Carneiro
f36f94a0e3 fix: malformed/misaligned markdown code fences (part 2) 2022-07-22 13:03:02 +02:00
Sebastian Ullrich
5d187b8beb fix: register tokens in parser quotation 2022-07-21 23:49:57 +02:00
Sebastian Ullrich
563d42f6d6 fix: make foApprox mdata-invariant 2022-07-21 14:05:47 -07:00
Andrés Goens
b36b50adb2 feat: syntax for using while condition in proofs 2022-07-21 16:57:35 +00:00
tydeu
bd7739d02e chore: add sanity check for SemanticTokenType/Modifier.names 2022-07-21 18:36:52 +02:00
Henrik Böving
8932878274 feat: Functor instance for List 2022-07-21 08:08:48 -07:00
E.W.Ayers
5dda654766 feat: make elabSimpArgs public
This is used in two places in mathlib4.
2022-07-21 05:37:56 -07:00
Leonardo de Moura
6d17e8abbf chore: ICERM notation demo 2022-07-21 08:13:20 -04:00
Leonardo de Moura
64b7b857f1 chore: ICERM attribute demo 2022-07-21 07:38:47 -04:00
Leonardo de Moura
977329ce1c chore: ICERM examples 2022-07-21 06:49:47 -04:00
Leonardo de Moura
b581c2fa17 fix: evalTactic
Another bug reported by Patrick.
2022-07-20 19:12:53 -04:00
Yuri de Wit
dc8e404d15 chore: renamed constant to opaque 2022-07-20 15:35:40 -07:00
Scott Morrison
aeeaaa6efc feat: size of a LocalContext 2022-07-20 15:31:10 -07:00
E.W.Ayers
b9c0fd2ab3 doc: fix AppBuilder docs 2022-07-20 15:30:30 -07:00
E.W.Ayers
5bf5abe84f test: update 533 test to include docstring 2022-07-20 15:30:30 -07:00
E.W.Ayers
caa2d9d80f doc: AppBuilder.lean 2022-07-20 15:30:30 -07:00
E.W.Ayers
14156f5e6a doc: fix assignExprMVar 2022-07-20 15:30:30 -07:00
Ed Ayers
0bfee4fe1f doc: apply suggestions from code review
Co-authored-by: Gabriel Ebner <gebner@gebner.org>
2022-07-20 15:30:30 -07:00
E.W.Ayers
64dec36ae3 doc: various docstrings 2022-07-20 15:30:30 -07:00
E.W.Ayers
8fe76ba9f4 doc: prelude Nat, Fin, USize 2022-07-20 15:30:30 -07:00
Sebastian Ullrich
c43a84ca30 fix: unsafe initialize 2022-07-20 22:37:01 +02:00
Sebastian Ullrich
b5417bdc6c chore: update stage0 2022-07-20 22:12:20 +02:00
Sebastian Ullrich
15bb3ccf6b chore: reduce TSyntax.Compat scope in Elab.Declaration 2022-07-20 22:12:20 +02:00
Sebastian Ullrich
cdb855d281 feat: support all sensible modifiers on (builtin_)initialize
Resolves #1324
2022-07-20 22:12:20 +02:00
Mario Carneiro
a2ef6bd19e fix: malformed/misaligned markdown code fences 2022-07-20 11:12:42 +02:00
Leonardo de Moura
3846dd60fd fix: evalTactic
This commit fixes bug reported by Patrick Massot.
It happened when using `macro_rules` and `elab_rules` for the same
`SyntaxNodeKind`.

It also fixes missing error messages when there is more than one
elaboration functions and there is `abortTactic` exception.

Remark: this commit also changes the evaluation order. Macros are
now tried before elaboration rules. The motivation is that macros are
already applied before elaboration functions in the term elaborator.
2022-07-19 23:28:14 -04:00
Leonardo de Moura
6558f56c29 fix: rename tactic 2022-07-19 23:28:14 -04:00
Leonardo de Moura
013b9e14f7 chore: fix typo 2022-07-19 23:28:14 -04:00
Gabriel Ebner
f2e7cbfbaf chore: use inaccessible name for RpcEncodingPacket 2022-07-19 22:55:42 +02:00
Gabriel Ebner
4ce56f7c05 fix: use field names if specified 2022-07-19 22:55:42 +02:00
Gabriel Ebner
59f528e678 fix: support empty inductives in json derive 2022-07-19 22:55:42 +02:00
Gabriel Ebner
2c0f8fac99 feat: support unused params in RpcEncoding deriver 2022-07-19 22:55:42 +02:00
Gabriel Ebner
d36552848c chore: hide weird RpcEncoding behind Nonempty 2022-07-19 22:55:42 +02:00
Gabriel Ebner
ed5e0f098c fix: support non-type params in RpcEncoding 2022-07-19 22:55:42 +02:00
Gabriel Ebner
62ede1fdfd chore: update test 2022-07-19 22:55:42 +02:00
Gabriel Ebner
cde339c2fb feat: support recursive types in RpcEncoding 2022-07-19 22:55:42 +02:00
Gabriel Ebner
b7bcb1616a chore: add inhabited instance for RpcEncoding
This allows us to define RpcEncodings as partial defs.
2022-07-19 22:55:42 +02:00
Gabriel Ebner
bcf2bf994b chore: exploit that command* is command as well 2022-07-19 22:55:42 +02:00
Gabriel Ebner
89dfff24ce chore: avoid $(mkIdent ``foo) 2022-07-19 22:55:42 +02:00
Gabriel Ebner
76e8a40237 chore: pick slightly nicer user-facing names 2022-07-19 22:55:42 +02:00
Gabriel Ebner
8b9c7ebf43 chore: simplify deriveWithRefInstance 2022-07-19 22:55:42 +02:00
Gabriel Ebner
bffd762822 feat: improve RpcEncoding derive test 2022-07-19 22:55:42 +02:00
Gabriel Ebner
c81b10f296 perf: implement Level.update* in Lean 2022-07-19 05:55:13 -07:00
Gabriel Ebner
eda3eae18e perf: implement Expr.update* in Lean 2022-07-19 05:55:13 -07:00
Sebastian Ullrich
1611cf63c3 fix: make document symbols request deterministic 2022-07-19 12:23:03 +02:00
tydeu
9d4a72bf6a feat: up to spec SemanticTokens/Type/Modifier 2022-07-19 11:57:57 +02:00
Sebastian Ullrich
987785242f fix: disable auto implicits in structure field default values 2022-07-18 21:09:56 -07:00
Ed Ayers
2d28a9dd94 doc: explain AttributeKind (#1316) 2022-07-18 21:04:18 -07:00
Scott Morrison
5c79973300 feat: allow an ApplyConfig argument at constructor tactic (#1319) 2022-07-18 21:02:31 -07:00
Leonardo de Moura
73fce217f6 test: for issue #1321 2022-07-18 23:50:41 -04:00
Leonardo de Moura
678cfda909 chore: update stage0 2022-07-18 23:44:45 -04:00
Leonardo de Moura
e1fc904786 feat: attributes on syntax
closes #1321
2022-07-18 23:37:11 -04:00
Leonardo de Moura
3325987be4 chore: fix tests 2022-07-18 23:18:59 -04:00
Leonardo de Moura
d95163641a chore: indent docstrings 2022-07-18 22:36:55 -04:00
Leonardo de Moura
3691fb2c34 chore: update stage0 2022-07-18 22:29:56 -04:00
Leonardo de Moura
c341d8432f feat: remove leading spaces from docstrings 2022-07-18 22:18:15 -04:00
Leonardo de Moura
da71dd3d77 chore: docstring 2022-07-18 22:16:32 -04:00
Leonardo de Moura
e8b58abdb2 chore: remove dead code 2022-07-18 22:16:32 -04:00
Sebastian Ullrich
be11e8e29b doc: missing linebreak 2022-07-18 22:31:16 +02:00
Mac
ad0288d767 feat: allow registering/chaining LSP handlers in initialize 2022-07-18 09:38:30 +02:00
Leonardo de Moura
5083d47e4d doc: some Syntax 2022-07-17 17:57:33 -04:00
Leonardo de Moura
7331fdf310 doc: Expr.lean 2022-07-17 17:28:28 -04:00
Leonardo de Moura
875b3c84b4 fix: bug at Match.lean 2022-07-17 14:55:57 -04:00
Leonardo de Moura
7cb011e94c doc: Expr.lean 2022-07-17 14:49:55 -04:00
Leonardo de Moura
2116f69315 chore: unused variables 2022-07-17 13:04:08 -04:00
Gabriel Ebner
3edf22f3f5 fix: crash in binop% 2022-07-17 09:57:56 -07:00
Sebastian Ullrich
8972cc9baf chore: Nix: cache Leanc-deps 2022-07-16 16:19:01 +02:00
Gabriel Ebner
ff3c67d1ad feat: recover from errors in attributes 2022-07-16 06:19:54 -07:00
Gabriel Ebner
69da058c03 fix: tests/lean/625.lean 2022-07-16 06:19:54 -07:00
Sebastian Ullrich
6bf7648941 doc: spurious space 2022-07-16 14:51:16 +02:00
Sebastian Ullrich
392c72db86 chore: Nix: renderLean/renderDir 2022-07-15 18:44:17 +02:00
Sebastian Ullrich
0835145246 feat: ppCategory 2022-07-15 10:58:29 +02:00
Leonardo de Moura
fb9b093cf9 chore: update example 2022-07-13 15:15:00 -07:00
Leonardo de Moura
94df25e99b chore: update example 2022-07-13 15:13:31 -07:00
Leonardo de Moura
cce2d3500e test: for issue #1301
closes #1301
2022-07-13 06:05:12 -07:00
larsk21
123fd801cb doc: linter utils 2022-07-13 10:35:37 +02:00
larsk21
9980123291 fix: check if variables are used first 2022-07-13 10:35:37 +02:00
larsk21
70aff92f8f fix: short-circuit ignore functions in unused variables linter 2022-07-13 10:35:37 +02:00
larsk21
9fcae6ffe9 fix: replace constant with opaque 2022-07-13 10:35:37 +02:00
larsk21
15f9c0585a fix: consider macro expansions in unused variables linter 2022-07-13 10:35:37 +02:00
larsk21
ced8df3e86 fix: references of variables with equal ranges 2022-07-13 10:35:37 +02:00
Leonardo de Moura
d0222990d0 chore: update stage0 2022-07-12 18:40:33 -07:00
Leonardo de Moura
b6860968ff fix: catch exception at elabMutualDef
closes #1301
2022-07-12 18:39:30 -07:00
Leonardo de Moura
fdef55339f fix: use binop% for elaborating ^
closes #1298
2022-07-12 18:20:02 -07:00
Leonardo de Moura
95f3f6b811 chore: update stage0 2022-07-12 18:14:29 -07:00
Leonardo de Moura
5e333191a2 feat: improve binop% and binrel% elaboration functions
Add support for operators that may not have homogeneous instances for
all types. For example, we have `HPow Nat Nat Nat` and `HPow Int Nat Int`,
but we don't have `HPow Int Int Int`.
2022-07-12 18:12:20 -07:00
Leonardo de Moura
a0e459999b chore: cleanup 2022-07-12 17:36:04 -07:00
Leonardo de Moura
d1f0db7072 fix: resumePostponed backtracking
Note that test for issue #1200 broke.
The bug fixed by this commit was allowing the example to be elaborated
correctly :(
Initially, the type of the discriminant is not available, and
`.none (α:=α)` can only be elaborated when the expected type is of the
form `C ...`. Lean then tries to elaborate the alternatives, learn
that the discriminant should be `Option ?m`, and fails because the
patterns still have metavariables after elaboration. Before the bug
fix, `resumePostpone` was **not** restoring the metavariable context,
and the assingnment would stay there. With this information, Lean
can now elaborate `.none (α:=α)`.
Although the bug had a positive impact in this case, it produced
incorrect behavior in other examples.
The fixed example looks reasonable. Thus, we will not reopen
issue #1200
2022-07-12 16:52:45 -07:00
Leonardo de Moura
ca4bd67746 chore: cleanup 2022-07-12 16:42:31 -07:00
Leonardo de Moura
b8ed579289 fix: fixes #1300 2022-07-12 14:08:47 -07:00
Leonardo de Moura
1235832314 feat: add runPendingTacticsAt (e : Expr) 2022-07-12 14:07:55 -07:00
Leonardo de Moura
e03e0bd254 refactor: split syntheticMVars into a map and todo-stack 2022-07-12 13:07:36 -07:00
Leonardo de Moura
64dbbb50f8 chore: cleanup 2022-07-12 09:26:00 -07:00
Leonardo de Moura
309f8d6bf9 fix: implicit arguments must be processed with at least default transparency
see #1299
2022-07-11 19:11:46 -07:00
Leonardo de Moura
5bd1f7bba1 fix: special support for higher order output parameters at isDefEqArgs
closes #1299
2022-07-11 19:05:24 -07:00
Leonardo de Moura
4d81c609cc chore: cleanup 2022-07-11 18:52:55 -07:00
Leonardo de Moura
3fd2250799 feat: add higherOrderOutParam to ParamInfo
Helper info for #1299
2022-07-11 18:52:01 -07:00
Leonardo de Moura
709f22c8e4 feat: add field dependsOnHigherOrderOutParam to ParamInfo
See issue #1299
2022-07-11 17:49:49 -07:00
Leonardo de Moura
591c53b3e9 chore: update stage0 2022-07-11 17:24:36 -07:00
Leonardo de Moura
f657aed798 feat: store outParam positions 2022-07-11 17:21:31 -07:00
Leonardo de Moura
0b1fde64ee chore: update stage0 2022-07-11 16:46:02 -07:00
Leonardo de Moura
dfc88ef99f chore: use a[i] 2022-07-11 16:44:52 -07:00
Leonardo de Moura
af1e670270 chore: fix typo 2022-07-11 15:46:54 -07:00
Gabriel Ebner
7e380bf236 chore: update stage0 2022-07-11 14:19:41 -07:00
Gabriel Ebner
a8cab84735 refactor: use computed fields for Expr 2022-07-11 14:19:41 -07:00
Gabriel Ebner
eba400543d refactor: use computed fields for Name 2022-07-11 14:19:41 -07:00
Gabriel Ebner
3176943750 refactor: use computed fields for Level 2022-07-11 14:19:41 -07:00
Gabriel Ebner
e0104b94e5 chore: update stage0 2022-07-11 14:19:41 -07:00
Gabriel Ebner
23113501f4 chore: prepare for Name refactoring 2022-07-11 14:19:41 -07:00
Gabriel Ebner
c100f45b77 feat: add simp lemmas and instances for LawfulBEq 2022-07-11 14:19:41 -07:00
Gabriel Ebner
86ccba8c87 chore: update release notes 2022-07-11 12:26:53 -07:00
Gabriel Ebner
a7e8a82e89 chore: require @[computedField] attribute 2022-07-11 12:26:53 -07:00
Gabriel Ebner
6fe3e36804 feat: support extern computed fields 2022-07-11 12:26:53 -07:00
Gabriel Ebner
243439a75c feat: support modifiers in computed fields 2022-07-11 12:26:53 -07:00
Gabriel Ebner
3a55228be0 chore: prepare for bootstrapping 2022-07-11 12:26:53 -07:00
Gabriel Ebner
b1eb022027 feat: computed fields 2022-07-11 12:26:53 -07:00
Gabriel Ebner
b48061ed23 feat: expose lower level compile function 2022-07-11 12:26:53 -07:00
Gabriel Ebner
18a299f576 feat: allow implementedBy on constructors and casesOn 2022-07-11 12:26:53 -07:00
Gabriel Ebner
5024c15a7a feat: add getConstInfoDefn 2022-07-11 12:26:53 -07:00
Gabriel Ebner
3776e3c925 feat: generalize unsafeCast to Sort 2022-07-11 12:26:53 -07:00
Leonardo de Moura
c568f11ddf feat: use default transparency at isDefEqProofIrrel
closes #1302
2022-07-11 12:11:10 -07:00
Leonardo de Moura
2fcd406f99 chore: remove sorry 2022-07-10 20:04:06 -07:00
Leonardo de Moura
ee0735760a feat: add instance : GetElem (List α) Nat α fun as i => i < as.length 2022-07-10 17:38:59 -07:00
Leonardo de Moura
0c5dfd78d7 chore: style 2022-07-10 15:26:26 -07:00
Leonardo de Moura
475c7e18cd chore: missing GetElem instances 2022-07-10 14:53:22 -07:00
Leonardo de Moura
fd0e9e1c52 chore: fix typo 2022-07-10 10:15:29 -07:00
Leonardo de Moura
351fc6ea04 chore: update release notes 2022-07-10 09:43:25 -07:00
Leonardo de Moura
4173a863d8 chore: cleanup 2022-07-10 09:43:12 -07:00
Leonardo de Moura
c82f74d094 chore: update stage0 2022-07-10 09:17:43 -07:00
Leonardo de Moura
451abdf79d fix: Level.update* functions
see #1291
2022-07-10 09:16:02 -07:00
Leonardo de Moura
ef4bf93315 chore: update stage0 2022-07-10 08:39:39 -07:00
Leonardo de Moura
ba606debf7 fix: Expr.update* issue
See #1291
2022-07-10 08:33:14 -07:00
Leonardo de Moura
f1d84a5096 perf: use dsimp := false in split tactic and while proving equation theorems
It is just a waste in these two cases.

It now takes 0.78 secs to process example on issue #1287.

closes #1287
2022-07-10 08:03:42 -07:00
Leonardo de Moura
4b543d5edd feat: add option for disabling dsimp during simp 2022-07-10 07:57:41 -07:00
Leonardo de Moura
7553dc12c0 chore: fix tests 2022-07-10 07:43:01 -07:00
Leonardo de Moura
394d49da58 perf: Expr.hasSorry and similar functions
Functions were ignoring sharing while traversing `Expr`.

Addresses performance problem exposed by #1287
2022-07-10 07:39:38 -07:00
Leonardo de Moura
2f1b80721e chore: avoid a[i]' h notation 2022-07-10 07:20:07 -07:00
Leonardo de Moura
35018dbea2 feat: unexpanders for a[i], a[i]' h, a[i]!, and a[i]? 2022-07-10 06:47:23 -07:00
Leonardo de Moura
23bae264fd perf: add cache for check (e : Expr) : MetaM Unit
Address one of the performance problems exposed by #1287
2022-07-09 20:09:15 -07:00
Leonardo de Moura
20d6b9c4aa doc: add new example 2022-07-09 17:04:08 -07:00
Leonardo de Moura
49951b87b9 chore: update release notes 2022-07-09 17:02:15 -07:00
Leonardo de Moura
6797e846d7 chore: update stage0 2022-07-09 16:46:00 -07:00
Leonardo de Moura
881589fc46 chore: remove parser workarounds 2022-07-09 16:42:39 -07:00
Leonardo de Moura
63067b896a chore: update stage0 2022-07-09 16:19:10 -07:00
Leonardo de Moura
aa52eebcdc feat: add instance GetElem (Array α) USize α fun xs i => LT.lt i.toNat xs.size where 2022-07-09 16:18:29 -07:00
Leonardo de Moura
1caff852fb chore: remove getOp functions 2022-07-09 16:09:28 -07:00
Leonardo de Moura
e55684b0c0 chore: update stage0 2022-07-09 16:04:54 -07:00
Leonardo de Moura
fd371ea812 chore: remove getOp builtin support 2022-07-09 16:04:17 -07:00
Leonardo de Moura
36ebccb822 chore: fix tests 2022-07-09 15:59:44 -07:00
Leonardo de Moura
e4b358a01e refactor: prepare to elaborate a[i] notation using typeclasses 2022-07-09 15:24:22 -07:00
Leonardo de Moura
e30ac86bd5 chore: update stage0 2022-07-09 14:44:47 -07:00
Leonardo de Moura
4c707d3b3c feat: use binop% to elaborate %-applications
Motivation: make sure the behavior is consistent with other arithmetic
operators.

This commit also removes the instance
```
instance : HMod (Fin n) Nat (Fin n) where
  hMod := Fin.modn
```
because we have a coercion from `Fin n` to `Nat`.
Thus, given `a : Fin n` and `b : Nat`, `a % b` is ambiguous.
2022-07-09 14:38:35 -07:00
Leonardo de Moura
305630cc23 fix: ElabAppArgs.finalize bug 2022-07-09 13:53:15 -07:00
Leonardo de Moura
a6151a9708 chore: update stage0 2022-07-09 12:20:35 -07:00
Leonardo de Moura
0074038405 fix: missing term info 2022-07-09 12:19:10 -07:00
Leonardo de Moura
2f6eb84ace chore: cleanup 2022-07-09 12:06:29 -07:00
Leonardo de Moura
2873a1b250 chore: unused variable warningns 2022-07-09 07:52:59 -07:00
Leonardo de Moura
defff00787 chore: remove workaround 2022-07-09 07:47:05 -07:00
Sebastian Ullrich
61b01ea3b3 Revert "chore: work around for type inference"
This reverts commit 6c64b1b20b.
2022-07-09 10:47:38 +02:00
Leonardo de Moura
b204ed8cee chore: update stage0 2022-07-08 17:33:11 -07:00
Leonardo de Moura
7e578bc122 chore: update stage0 2022-07-08 17:30:07 -07:00
Leonardo de Moura
bdaabd4e7b feat: propagate return type to for-in block 2022-07-08 17:29:30 -07:00
Leonardo de Moura
71edf731f9 fix: missing withFreshMacroScope 2022-07-08 17:25:29 -07:00
Leonardo de Moura
b8991586bd chore: update stage0 2022-07-08 16:55:44 -07:00
Leonardo de Moura
eb06b90b17 chore: add workaround 2022-07-08 16:54:44 -07:00
Leonardo de Moura
39f598a3e1 chore: update Lake 2022-07-08 16:42:18 -07:00
Leonardo de Moura
77b68688e7 chore: update stage0 2022-07-08 16:36:52 -07:00
Leonardo de Moura
d50b33175d feat: improve forIn elaborator element type propagation 2022-07-08 16:34:42 -07:00
Leonardo de Moura
7cf31f7360 chore: update comment 2022-07-08 15:34:09 -07:00
Leonardo de Moura
3c7053635b chore: update stage0 2022-07-08 15:31:26 -07:00
Leonardo de Moura
e4e0f775d6 feat: improve outParam as result type support 2022-07-08 15:29:48 -07:00
Sebastian Ullrich
32118a832d fix: update to adjusted Lake update 2022-07-08 23:24:30 +02:00
Sebastian Ullrich
0f6bda61c9 chore: Nix: buildLeanPackage devShell 2022-07-08 23:24:04 +02:00
Sebastian Ullrich
f5eaa525b3 chore: disable Nix macOS once more
I guess it's not that attractive without ARM support anyway
2022-07-08 23:01:50 +02:00
Sebastian Ullrich
8f70c346fd chore: Nix: fix develop shell 2022-07-08 21:49:50 +02:00
Leonardo de Moura
2472a6a1ea chore: fix build
Another ugly hack to survive until we port the code generator to Lean.
2022-07-08 10:34:50 -07:00
Sebastian Ullrich
7ee5203dbb chore: update stage0 2022-07-08 19:06:10 +02:00
Sebastian Ullrich
d7bcc271be refactor: avoid nested sequence in simpleBinder 2022-07-08 19:06:10 +02:00
Sebastian Ullrich
75b0b50983 fix: backtrack on unexpected non-identifier in parenthesizer 2022-07-08 14:49:08 +02:00
Sebastian Ullrich
4f1c3faa6e chore: Nix: re-enable nix develop on bare derivations 2022-07-08 14:49:08 +02:00
Sebastian Ullrich
6d1b2094e9 chore: nix flake update
This comes with ccache 4.6.1, which seems to fix the specific
miscompilation I managed to reproduce with 4.6.0
2022-07-08 13:46:57 +02:00
Leonardo de Moura
5455c16fc5 chore: update stage0 2022-07-07 23:41:00 -07:00
Leonardo de Moura
bf91956449 fix: add workaround for issue #1293
This is a temporary hack until we port the C++ code to Lean.

closes #1293
2022-07-07 23:39:35 -07:00
Leonardo de Moura
438fce8da7 chore: update stage0 2022-07-07 23:03:06 -07:00
Leonardo de Moura
8f8bb8c940 chore: update stage0 2022-07-07 23:01:06 -07:00
Leonardo de Moura
6ef81e1cdf fix: bug at the code specialization cache
closes #1292
2022-07-07 22:59:18 -07:00
Leonardo de Moura
d6a73bf03c chore: update stage0 2022-07-07 20:26:40 -07:00
Leonardo de Moura
c9771fa1b2 chore: unused variables 2022-07-07 20:24:18 -07:00
Leonardo de Moura
58619291e9 feat: better qualified name support in recursive definitions 2022-07-07 20:15:25 -07:00
Leonardo de Moura
db47664d4a fix: discrepancy between isDefEq and whnf for transparency mode instances 2022-07-07 15:39:58 -07:00
Leonardo de Moura
dd924e5270 chore: remove codegen option
We should use `noncomputable` modifier instead.

closes #1288
2022-07-07 08:18:30 -07:00
Leonardo de Moura
fce7697151 fix: def _root_ and dotted notation in recursive definitions
closes #1289
2022-07-07 07:57:51 -07:00
Sebastian Ullrich
305866dba2 feat: "linting" profiler metric 2022-07-07 14:23:59 +02:00
Sebastian Ullrich
29bdc0ceac fix: bound syntax kind at v:(ppSpace ident) etc. 2022-07-07 11:49:35 +02:00
Leonardo de Moura
0c30372f93 doc: add todo for expandDelayedAssigned 2022-07-06 20:08:12 -07:00
Leonardo de Moura
2494f1d4a4 chore: fix doc 2022-07-06 19:56:25 -07:00
Leonardo de Moura
ddae76aed2 chore: update stage0 2022-07-06 19:46:15 -07:00
Leonardo de Moura
0cecbe2ce6 chore: update stage0 2022-07-06 19:43:57 -07:00
Leonardo de Moura
71550c55a9 fix: @ scope 2022-07-06 19:42:43 -07:00
Leonardo de Moura
2fcb784372 feat: default value for coeAtOutParam parameter 2022-07-06 19:00:32 -07:00
Leonardo de Moura
01d0ca8cfe doc: coeAtOutParam todo's 2022-07-06 18:58:40 -07:00
Leonardo de Moura
f8c7bd71aa fix: position information for toStream application at do-notation 2022-07-06 18:50:45 -07:00
Leonardo de Moura
c5e00c2bde fix: do not create coercion placeholder if function is partially applied 2022-07-06 18:38:11 -07:00
Leonardo de Moura
645c3e777d feat: disable coeAtOutParam when @ (aka explicit = true) is used 2022-07-06 18:31:39 -07:00
Leonardo de Moura
0425fabf8f test: test for output parameter + coercion issue 2022-07-06 16:55:08 -07:00
Leonardo de Moura
42548adc5d fix: typo at addImplicitArg 2022-07-06 16:53:57 -07:00
Leonardo de Moura
9ba65fee83 fix: a coercion around an output parameter (and promotion to synthetic opaque) should only be used if there in no other way to infer parameter
We need this refinement for declarations such as
```
def add_one {X} [Trait X] [One (Trait.R X)] [HAdd X (Trait.R X) X] (x : X) : X := x + (One.one : (Trait.R X))
```
from test 948.lean
2022-07-06 16:38:39 -07:00
Leonardo de Moura
ab16278ce4 fix: missing synthesizeSyntheticMVars at elabSubst 2022-07-06 16:15:29 -07:00
Leonardo de Moura
aa9167834b fix: coeAtOutParam can only be used after Coe.lean 2022-07-06 16:06:11 -07:00
Leonardo de Moura
55ad7beb8d feat: add coercion placeholder for applications that return an output parameter of a local instance 2022-07-06 15:42:39 -07:00
Leonardo de Moura
e7bc114ba2 fix: bug at withAssignableSyntheticOpaque 2022-07-06 15:24:17 -07:00
Leonardo de Moura
ec4794ad10 chore: use withAssignableSyntheticOpaque 2022-07-06 15:24:17 -07:00
Leonardo de Moura
608a306ef0 refactor: simplify/cleanup DelayedMetavarAssignment 2022-07-06 15:24:17 -07:00
Leonardo de Moura
81ed8b0b32 chore: cleanup 2022-07-06 15:24:17 -07:00
Sebastian Ullrich
d679044a9b chore: Nix: use --deps-json for faster, single IFD per package 2022-07-06 16:12:30 +02:00
Sebastian Ullrich
ec991f3761 chore: update stage0 2022-07-06 16:12:30 +02:00
Sebastian Ullrich
775ed70a84 feat: add lean --print-deps-json 2022-07-06 16:12:30 +02:00
Sebastian Ullrich
a16eff2996 chore: Nix: implement roots 2022-07-06 16:12:30 +02:00
Leonardo de Moura
38e1f6ba82 fix: missing instantiateMVars 2022-07-05 20:45:53 -07:00
Leonardo de Moura
0a5df7cd6d chore: style 2022-07-05 20:45:53 -07:00
tydeu
6e4bca57c8 chore: update Lake 2022-07-05 17:27:41 -07:00
Leonardo de Moura
91d48c9150 chore: update stage0 2022-07-05 14:29:45 -07:00
Leonardo de Moura
627594b88a fix: "dot"-notation should apply default instances before failing
See new test for motivating example.
2022-07-05 14:27:55 -07:00
Leonardo de Moura
13a49da496 chore: update stage0 2022-07-05 13:25:50 -07:00
Leonardo de Moura
2b2d4245dc fix: extensible tactics bug
See comment at `expandMacros`
2022-07-05 13:20:22 -07:00
Siddharth Bhat
e6629b760d fix: Clearer error message for cast(▸) notation
The old error message said:

```
throwError "invalid `▸` notation,
expected type{indentExpr expectedType}\ndoes contain
equation left-hand-side nor right-hand-side{indentExpr heqType}"
```

The phrase `does contain ... nor ..` seems gramatically incorrect.
What was (probably) intended was `does **not** contain ... nor ...`.

We take the opportunity to clean up the error message and
be clearer that the equality does not contain the expected result type.
2022-07-05 09:01:09 -07:00
Sebastian Ullrich
6303fb77d2 fix: expansion info for macro commands
TODO: investigate that pp error
2022-07-05 13:18:59 +02:00
tydeu
bff560759e feat: add missing literal TSyntax helpers 2022-07-05 13:18:58 +02:00
Leonardo de Moura
2061c9bbea chore: reduce test size
TODO: investigate why there is a stack overflow in the CI.
I didn't manage to reproduce it on my machine.
2022-07-04 13:58:06 -07:00
Leonardo de Moura
ffc90f6a35 fix: bug at ll_infer_type 2022-07-04 13:55:55 -07:00
Leonardo de Moura
7668750cb5 chore: update stage0 2022-07-04 07:25:35 -07:00
Leonardo de Moura
1999db1d7c test: add test for performance issue
This issue has bee reported at
https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/deterministic.20timeout.20with.20structures/near/288180087
2022-07-04 07:20:12 -07:00
Leonardo de Moura
c434e4e096 chore: remove old tests 2022-07-04 07:18:07 -07:00
Leonardo de Moura
2446c64a99 chore: cleanup 2022-07-04 07:15:04 -07:00
Leonardo de Moura
64edb50687 chore: fix tests 2022-07-04 06:35:21 -07:00
Leonardo de Moura
f77ebae87f fix: withResetUsedAssignment 2022-07-04 06:33:42 -07:00
Leonardo de Moura
05a28af429 fix: skipDefEqCache 2022-07-04 06:33:32 -07:00
Leonardo de Moura
88fc0b2503 fix: isAssigned-like functions should set usedAssignment 2022-07-04 06:20:37 -07:00
Leonardo de Moura
6b2d2ffac6 fix: preserve usedAssignment flag when replacing MetavarContext 2022-07-04 05:49:54 -07:00
Leonardo de Moura
64d46272c2 fix: do not cache when smart unfolding is disabled 2022-07-04 05:48:35 -07:00
Leonardo de Moura
a1413b8fa1 feat: cache failures at isDefEq
We can compile Lean with these changes, but 3 tests are still broken.
This cache is used to address a performance issue reported at
  https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/deterministic.20timeout.20with.20structures/near/288180087
2022-07-03 21:52:01 -07:00
Leonardo de Moura
76245b39d1 chore: remove dead field
We have remove the old frontend a long time ago.
2022-07-03 15:38:48 -07:00
Leonardo de Moura
aae657571f doc: docstrings for src/Lean/Meta/Basic.lean 2022-07-03 15:32:15 -07:00
Leonardo de Moura
b78925d9bb chore: update stage0 2022-07-03 15:01:58 -07:00
Leonardo de Moura
757171db1f feat: add String.get! and s[i]! notation for String 2022-07-03 14:59:44 -07:00
Gabriel Ebner
07a3cd6980 chore: fix tests 2022-07-03 22:46:59 +02:00
Gabriel Ebner
141b110ff1 feat: add more typed syntax coercions 2022-07-03 22:46:59 +02:00
Gabriel Ebner
922ef23112 fix: do not ignore syntax coercions
Syntax coercions do not need to be the identity.  See for example
``Coe (TSyntax `ident) (TSyntax `declId)``.
2022-07-03 22:46:59 +02:00
Gabriel Ebner
ddf77a8c6d chore: style 2022-07-03 22:46:59 +02:00
Gabriel Ebner
bec0bbc351 fix: replace dangerous instance by CoeTail
In order to guarantee termination of type class synthesis when resolving
coercions, a good rule of thumb is that the instances should not
introduce metavariables (during TC synthesis).  For common coercion type
classes this means:

 - `Coe T S`, `CoeTail T S`: the variables of `T` must be a subset of those of `S`
 - `CoeHead T S`: the variables of `S` must be a subset of those of `T`

If these rules are not followed, we can easily get nontermination.  In
this case: `CoeTC Foo Syntax` is reduced to `CoeTC Foo (TSyntax ?m_1)`
using the (dangerous) `Coe (TSyntax k) Syntax` instance, to which we can
then apply the otherwise fine `Coe (TSyntax [k]) (TSyntax (k'::ks))`
coercion infinitely often.
2022-07-03 22:46:59 +02:00
Gabriel Ebner
3d5c5553d9 fix: add missing coercion instance for CoeHead+CoeTail 2022-07-03 22:46:59 +02:00
Leonardo de Moura
03ce7cb17c fix: dependent pattern matching bug
closes #1279
Originally reported at https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/case.20in.20dependent.20match.20not.20triggering.20.28.3F.29/near/288328239
2022-07-03 13:25:12 -07:00
Leonardo de Moura
68024b11a4 fix: simp_all bug when goal has duplicate hypotheses 2022-07-03 12:44:53 -07:00
Sebastian Ullrich
2f67295c7d feat: strengthen pp* signatures 2022-07-03 19:14:49 +02:00
Sebastian Ullrich
146aefd085 feat: ppTactic 2022-07-03 19:00:13 +02:00
Sebastian Ullrich
5e46c0865e doc: update LeanInk 2022-07-03 17:56:51 +02:00
Leonardo de Moura
8f83999202 chore: update release notes 2022-07-03 06:26:47 -07:00
Leonardo de Moura
5e3a3a6c21 chore: remove notation a[i,h] for a[⟨i, h⟩] 2022-07-03 06:24:26 -07:00
kzvi
7326c817d2 fix: fix typos in deBruijn.lean and phoas.lean examples 2022-07-02 16:12:05 -07:00
Leonardo de Moura
0bdab9b4f7 doc: update release notes 2022-07-02 16:06:57 -07:00
Leonardo de Moura
a1d09f1ced chore: update stage0 2022-07-02 15:57:22 -07:00
Leonardo de Moura
a0fdc2d050 chore: fix tests 2022-07-02 15:57:05 -07:00
Leonardo de Moura
54c60d4c2d feat: a[i] and a[i]! notation for Subarrays 2022-07-02 15:54:34 -07:00
Leonardo de Moura
a2456c3a0f feat: add notation a[i, h] for a[⟨i, h⟩] 2022-07-02 15:50:49 -07:00
Leonardo de Moura
eb115abcbe chore: update stage0 2022-07-02 15:37:13 -07:00
Leonardo de Moura
e81a847ba3 fix: doc/array.md 2022-07-02 15:36:01 -07:00
Leonardo de Moura
4568fe755c chore: fix tests 2022-07-02 15:25:06 -07:00
Leonardo de Moura
b3ea1fc925 feat: a[i] notation for arrays now uses i : Fin a.size 2022-07-02 15:19:38 -07:00
Leonardo de Moura
e4b472a9a2 chore: fix tests 2022-07-02 15:17:01 -07:00
Leonardo de Moura
2409840aa8 chore: update stage0 2022-07-02 15:12:53 -07:00
Leonardo de Moura
2ebcf29cde chore: use a[i]! for array accesses that may panic 2022-07-02 15:12:05 -07:00
Leonardo de Moura
88a0506ab0 chore: update stage0 2022-07-02 10:07:09 -07:00
Leonardo de Moura
3f3cd22366 feat: add Array.getOp! and Array.getOp?
Add warning when `Array.getOp` is used. TODO: replace `Array.getOp`
with safe version
2022-07-02 10:06:05 -07:00
Leonardo de Moura
8bf90b128e fix: interactive test driver 2022-07-02 10:01:04 -07:00
Leonardo de Moura
418607f3ad chore: update lake 2022-07-02 09:59:42 -07:00
Leonardo de Moura
e8935d996b chore: String.get?, String.getOp?, and remove String.getOp 2022-07-02 09:59:04 -07:00
Leonardo de Moura
e42b82d775 chore: update stage0 2022-07-02 07:35:07 -07:00
Leonardo de Moura
053bc889a3 feat: elaborate a[i]! and a[i]? 2022-07-02 07:29:58 -07:00
Leonardo de Moura
cbe05441a5 chore: update stage0 2022-07-02 07:29:58 -07:00
Leonardo de Moura
131e7be8c5 feat: add a[i]? and a[i]! parsers 2022-07-02 07:29:58 -07:00
Sebastian Ullrich
0896180f12 chore: CI: downgrade Nix 2022-07-02 12:19:30 +02:00
tydeu
515541709a chore: fix tests 2022-07-02 10:37:22 +02:00
tydeu
29be868342 chore: update Lake 2022-07-02 10:37:22 +02:00
Leonardo de Moura
a639eb185c fix: dsimp zeta issue 2022-07-01 06:42:09 -07:00
Leonardo de Moura
5294a39ec4 feat: add Float.ceil, Float.floor, and Float.round 2022-07-01 06:27:30 -07:00
Leonardo de Moura
d9be3e0017 doc: add new bullet 2022-06-30 19:17:29 -07:00
Leonardo de Moura
0b27d26c99 doc: add quick tour video 2022-06-30 19:16:25 -07:00
Leonardo de Moura
d1f966fa6d doc: docstrings for src/Lean/Elab/Term.lean 2022-06-30 19:01:34 -07:00
Leonardo de Moura
14260f454b feat: improve is_def_eq for projections
It implements in the kernel the optimization in the previous commit.

This commit addresses the following issue raised on Zulip.
https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/unfold.20essentially.20loops/near/288083209
2022-06-30 17:50:44 -07:00
Leonardo de Moura
dba1f79170 feat: improve isDefEq for projections
When solving `a.i =?= b.i`, we first reduce `a` and `b` without using
delta reduction. If at least one become a structure, we reduce the
projection. Otherwise, we try to solve `a =?= b`, only reduce `a.i`
and `b.i` if it fails.
2022-06-30 17:00:43 -07:00
Leonardo de Moura
f3bb0be045 feat: add flag to control projection reduction at whnfCore 2022-06-30 16:48:00 -07:00
Leonardo de Moura
2c152dae7d chore: remove unnecessary partial 2022-06-30 15:47:31 -07:00
Leonardo de Moura
e9e75af834 doc: Lean/Meta/Basic.lean
Add some docstrings
2022-06-30 13:32:19 -07:00
Leonardo de Moura
f6b6b36f47 chore: indentation 2022-06-29 16:45:59 -07:00
Leonardo de Moura
467ac9d98a feat: add support for CommandElabM at #eval
Note that it does not use `MetaEval` to execute the term of type
`CommandEval`. Thus, we can now use `#eval` to execute simple commands.

see #1256
2022-06-29 16:34:49 -07:00
Leonardo de Moura
d83a11bac5 chore: expose exprToSyntax 2022-06-29 16:02:01 -07:00
Leonardo de Moura
66711a9974 chore: update stage0 2022-06-29 15:40:57 -07:00
Leonardo de Moura
d4eed2e490 test: test for #1267 2022-06-29 15:40:13 -07:00
Leonardo de Moura
e8891986f2 chore: update stage0 2022-06-29 15:37:30 -07:00
Leonardo de Moura
95efa3dcd2 fix: withPosition case at MacroArgUtil
fixes #1267 after update stage0
2022-06-29 15:35:34 -07:00
Leonardo de Moura
1b7fab4497 chore: add binder types 2022-06-29 15:31:10 -07:00
Leonardo de Moura
e968dfb68c feat: elaborate do notation even when expected type is not available
see issue #1256
2022-06-29 13:30:06 -07:00
Leonardo de Moura
598898a087 fix: fixes #1265 2022-06-29 12:41:14 -07:00
Leonardo de Moura
15e2a7d5b4 feat: report errors an unassigned metavars at #eval
See #1256
2022-06-29 11:53:33 -07:00
Sebastian Ullrich
3ed910a043 refactor: rename AsyncList.asyncTail to delayed
I often found the terminology confusing as it is inconsistent with
`List.tail`
2022-06-29 17:08:15 +02:00
Sebastian Ullrich
ae683af9c2 refactor: merge AsyncList.updateFinishedPrefix/finishedPrefix
We only ever use both of them together, and forgetting to call the first
one first could lead to subtle bugs.
2022-06-29 17:08:15 +02:00
Sebastian Ullrich
c8fb72195b feat: print panic backtraces on Linux 2022-06-29 16:29:35 +02:00
Leonardo de Moura
a888b21bce fix: compiler bug at And.casesOn
Fixes issue reported at https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/.28libc.2B.2Babi.29.20lean.3A.3Aexception.3A.20incomplete.20case/near/287839995
2022-06-29 06:56:17 -07:00
Sebastian Ullrich
10b0eca41f chore: CI: minor 2022-06-29 12:43:01 +02:00
Leonardo de Moura
98b8e300e1 feat: add evalTerm and Meta.evalExpr
These functions were in Mathlib 4.
2022-06-28 19:14:40 -07:00
Leonardo de Moura
fc7c1d1053 chore: remove unnecessary set_option 2022-06-28 17:37:10 -07:00
Leonardo de Moura
87a72e4bbe chore: update stage0 2022-06-28 16:57:11 -07:00
Sebastian Ullrich
80217cfa90 fix: asynchronous head snapshot fallout 2022-06-28 16:54:29 -07:00
Sebastian Ullrich
99f5e94efe feat: MonadExcept.ofExcept 2022-06-28 16:54:29 -07:00
Sebastian Ullrich
c64ac02ffc fix: declModifiers syntax kind 2022-06-28 22:35:13 +02:00
Sebastian Ullrich
a9cc57c81c chore: CI: more cache setup 2022-06-28 22:31:51 +02:00
Sebastian Ullrich
920fa1109b chore: CI: ccache permissions 2022-06-28 18:53:36 +02:00
Sebastian Ullrich
9816331562 chore: clean up bootstrapping cleanup 2022-06-28 16:28:36 +02:00
Sebastian Ullrich
995d92d10e chore: CI: fix ccache cache group 2022-06-28 16:24:10 +02:00
Sebastian Ullrich
8f3fda4777 chore: update stage0 2022-06-28 16:01:43 +02:00
Sebastian Ullrich
77c6f433c7 chore: clean up bootstrapping workarounds 2022-06-28 16:01:07 +02:00
Sebastian Ullrich
74c4437874 chore: CI: simplify Nix setup, bring back macOS 2022-06-28 12:50:19 +02:00
Sebastian Ullrich
5bba20d6a9 refactor: revert toParserDescr signature change 2022-06-28 11:50:59 +02:00
Sebastian Ullrich
89a101e9b8 refactor: remove group(·)s 2022-06-28 11:50:59 +02:00
Sebastian Ullrich
9490328429 chore: update stage0 2022-06-28 11:50:59 +02:00
Sebastian Ullrich
eab64997cd fix: auto-group syntax parsers where necessary 2022-06-28 11:50:59 +02:00
Timo
e49a81bb56 doc: fix typo 2022-06-27 19:48:45 -07:00
Leonardo de Moura
34dc2572f3 fix: make sure OfScientific Float instance is never unfolded during type class resolution
This commit fixes issue reported at
https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/deterministic.20timeout/near/287654818

Type class resolution was diverging when trying to synthesize
```lean
 HSub (optParam Float 0.0) (optParam Float 1.0) ?m.472
```
and Lean was diverging while unfolding
```lean
 instance : OfScientific Float where
   ofScientific m s e :=
     if s then
       let s := 64 - m.log2 -- ensure we have 64 bits of mantissa left after division
       let m := (m <<< (3 * e + s)) / 5^e
       Float.ofBinaryScientific m (-4 * e - s)
     else
       Float.ofBinaryScientific (m * 5^e) e
```
was being unfolded.

Anothe potential solution for the problem above is to erase the
`optParam` annotations before performing type class resolution.
2022-06-27 17:40:34 -07:00
Sebastian Ullrich
ca19ce1e6f chore: CI: fix Windows 2022-06-28 00:38:19 +02:00
Sebastian Ullrich
18d2296b1c doc: add typed macros to RELEASES.md 2022-06-27 23:42:13 +02:00
Leonardo de Moura
5901fef43a feat: protected aliases
See message: https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/Namespace-based.20overloading.20does.20not.20find.20exports/near/287633118
2022-06-27 13:56:58 -07:00
Sebastian Ullrich
19c2644d88 chore: add more comments 2022-06-27 22:37:02 +02:00
Sebastian Ullrich
544a046678 chore: use Syntax.Level 2022-06-27 22:37:02 +02:00
Sebastian Ullrich
22475b8669 refactor: introduce common TSyntax abbreviations 2022-06-27 22:37:02 +02:00
Sebastian Ullrich
db42874be4 chore: update Lake 2022-06-27 22:37:02 +02:00
Sebastian Ullrich
e47f248161 doc: TSyntax 2022-06-27 22:37:02 +02:00
Sebastian Ullrich
8b4d8b8dc9 feat: TSyntax singleton kind unexpanders 2022-06-27 22:37:02 +02:00
Sebastian Ullrich
6f7ff3b492 chore: remove unnecessary type annotations 2022-06-27 22:37:02 +02:00
Sebastian Ullrich
6af00ff23e chore: changes to placate coercions 2022-06-27 22:37:02 +02:00
Sebastian Ullrich
d9cfda4893 refactor: make more use of quotations
Automatically fixes many TSyntax type errors
2022-06-27 22:37:02 +02:00
Sebastian Ullrich
7043c4ebe7 refactor: mkSimpleDelab 2022-06-27 22:37:02 +02:00
Sebastian Ullrich
0b28f059f6 chore: work around "unknown free variable" bug 2022-06-27 22:37:02 +02:00
Sebastian Ullrich
3a56db2812 chore: fix tests 2022-06-27 22:37:02 +02:00
Sebastian Ullrich
c3585dbbbb chore: raw syntax kind accesses
Sometimes just checking the kind simply is the simplest solution.
2022-06-27 22:37:02 +02:00
Sebastian Ullrich
c2166fc602 chore: work around parameterized parser syntax kinds
We should find a better solution for calling parameterized parsers such
as `matchAlt` than these helper definitions that confuse the antiquotations.
2022-06-27 22:37:02 +02:00
Sebastian Ullrich
d499e67c87 fix: incorrect antiquotation kind annotations
Apparently, none of them led to incorrect syntax trees, but `TSyntax`
still disapproves.
2022-06-27 22:37:02 +02:00
Sebastian Ullrich
6c64b1b20b chore: work around for type inference
It seems type information often flows from the body to the loop
variable, which is problematic with coercions.
2022-06-27 22:37:02 +02:00
Sebastian Ullrich
5e334b3e90 chore: postpone TSyntax adoption for some parts
The namespace `TSyntax.Compat` can be opened for a coercion
`Syntax -> TSyntax k` for any `k`, as otherwise this PR would never be done.
2022-06-27 22:37:02 +02:00
Sebastian Ullrich
fe22d84143 fix: unclear TSyntax breakage 2022-06-27 22:37:02 +02:00
Sebastian Ullrich
86cd656fc6 refactor: adapt raw syntax manipulations to TSyntax
Sometimes there's just no structure to work on
2022-06-27 22:37:02 +02:00
Sebastian Ullrich
498c7a6a97 refactor: remove some unnecessary antiquotation kind annotations
These are just the ones I stumbled upon, there should be a lot more now
rendered obsolete by the coercions.
2022-06-27 22:37:02 +02:00
Sebastian Ullrich
a78302243c refactor: strengthen Syntax signatures
Most notable change: `Quote` is now parameterized by the target kind.
Which means that `Name` etc. could actually have different
implementations for quoting into `term` and `level`, if that need ever
arises.
2022-06-27 22:37:02 +02:00
Sebastian Ullrich
f90e4ae30c feat: more TSyntax API & coercions 2022-06-27 22:37:02 +02:00
Sebastian Ullrich
a12cde41e1 chore: work around macro limitations
It would be nice if `macro` was as expressive as syntax quotations, but
right now it's not.
2022-06-27 22:37:02 +02:00
Sebastian Ullrich
c202a2c013 feat: more antiquotation kinds 2022-06-27 22:37:02 +02:00
Sebastian Ullrich
7bc95d3a95 chore: update stage0 2022-06-27 22:37:02 +02:00
Sebastian Ullrich
9db8bac040 chore: prepare for next stage 2022-06-27 22:37:02 +02:00
Sebastian Ullrich
d50b1aab89 feat: <|> may produce a choice node of antiquotations 2022-06-27 22:37:02 +02:00
Sebastian Ullrich
ab08bffbec chore: Nix: fix stage0-from-input 2022-06-27 22:37:02 +02:00
Sebastian Ullrich
4b78d02a5e fix: do not discriminate anonymous antiquots after all 2022-06-27 22:37:02 +02:00
Sebastian Ullrich
9b71fbb461 chore: default pp.rawOnError to true for stage 0 2022-06-27 22:37:02 +02:00
Sebastian Ullrich
43ba121e98 feat: upgrade TSyntax to union of kinds 2022-06-27 22:37:02 +02:00
Sebastian Ullrich
3a61cc247e chore: introduce doSeq antiquotation 2022-06-27 22:37:02 +02:00
Sebastian Ullrich
330245816c fix: macro: inferred syntax kinds for literal parsers 2022-06-27 22:37:02 +02:00
Sebastian Ullrich
2ef3636022 fix: elaborating category quotations 2022-06-27 22:37:02 +02:00
Sebastian Ullrich
4588b1ec90 fix: ignore withPosition when binding macro arguments
Would be nice to generalize this at some point
2022-06-27 22:37:02 +02:00
Sebastian Ullrich
80a92cceeb fix: avoid choice nodes with LeadingIdentBehavior.both 2022-06-27 22:37:02 +02:00
Sebastian Ullrich
e6954bb4f3 fix: quote Name.anonymous 2022-06-27 22:37:02 +02:00
Sebastian Ullrich
7d48d125da fix: store syntax kinds of parser aliases in order to construct correct antiquotations in macro and elab 2022-06-27 22:37:02 +02:00
Sebastian Ullrich
2c54a0d17a feat: allow anonymous antiquotations for tacticSeq 2022-06-27 22:37:02 +02:00
Sebastian Ullrich
df499a5b64 feat: early coercion from TSyntax to Syntax 2022-06-27 22:37:02 +02:00
Sebastian Ullrich
c2b4c37792 refactor: make Init.Coe independent of Init.Notation 2022-06-27 22:37:02 +02:00
Sebastian Ullrich
3b3961a89b chore: disable some anonymous antiquotations 2022-06-27 22:37:02 +02:00
Sebastian Ullrich
8bbae8b8da feat: introduce TSyntax 2022-06-27 22:37:02 +02:00
Sebastian Ullrich
292d24ba19 feat: always store quoted kind in antiquotation kind 2022-06-27 22:37:02 +02:00
Sebastian Ullrich
0bd864deca fix: nesting of pattern info nodes 2022-06-27 22:37:02 +02:00
Leonardo de Moura
6ebae968a7 feat: use IO.getRandomBytes to initialize random seed
See https://github.com/leanprover/lean4-samples/pull/2
2022-06-27 13:01:20 -07:00
Leonardo de Moura
f4e083d507 feat: dot notation and aliases
This commit addresses the issue raised at
https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/Namespace-based.20overloading.20does.20not.20find.20exports/near/282946185
2022-06-27 12:42:25 -07:00
Leonardo de Moura
fc25689f21 feat: add Syntax.eraseSuffix? 2022-06-27 10:30:57 -07:00
Leonardo de Moura
3f0a9eb424 test: add test for issue #1253
closes #1253
2022-06-27 09:56:47 -07:00
Leonardo de Moura
c498285d94 chore: add missing double backtick 2022-06-27 09:56:47 -07:00
Sebastian Ullrich
3eeeca22e2 chore: lean-gdb: recursive values & tag 2022-06-26 18:47:47 +02:00
Sebastian Ullrich
5a0c3b8d80 fix: String.isNat 2022-06-25 18:42:08 +02:00
Wojciech Nawrocki
aacfd11508 feat: boolean inequality lemmas 2022-06-25 11:18:09 +02:00
E.W.Ayers
cc9293af09 doc: isDefEq explain mvar levels 2022-06-24 15:24:52 -07:00
Sebastian Ullrich
8979ed42a4 refactor: file worker: wait on header task before dispatching requests 2022-06-24 19:02:00 +02:00
Sebastian Ullrich
e14b4ab0e4 feat: file worker: make header snapshot asynchronous 2022-06-24 19:02:00 +02:00
Leonardo de Moura
220d2e3816 feat: add filterTR and [csimp] theorem 2022-06-24 06:40:38 -07:00
Leonardo de Moura
1fd2b17a92 fix: bug at addDependencies
closes #1247
2022-06-24 06:20:00 -07:00
Gabriel Ebner
ec4200fc75 chore: remove unnecessary ppLine 2022-06-24 10:59:55 +02:00
Gabriel Ebner
233a787e65 chore: add test for sepByIndent.formatter 2022-06-24 10:59:55 +02:00
Gabriel Ebner
d5142ddeb8 chore: add sepByIndent.formatter 2022-06-24 10:59:55 +02:00
Gabriel Ebner
733f220ee3 feat: $[...]* antiquotations for sepByIndent 2022-06-24 10:59:55 +02:00
Leonardo de Moura
09c4af26fc fix: ConstantInfo.all for consistency 2022-06-23 16:41:54 -07:00
Leonardo de Moura
88fae4e3d6 chore: update stage0 2022-06-23 16:41:05 -07:00
Leonardo de Moura
98c775da34 feat: save mutual block information for definitions/theorems/opaques 2022-06-23 16:39:51 -07:00
Leonardo de Moura
ea3e27bbc4 chore: update stage0 2022-06-23 16:13:49 -07:00
Leonardo de Moura
69a446c8d1 feat: add field all to DefinitionVal and TheoremVal
Remark: we need an update stage0, and the field is not being updated
correctly set yet.
2022-06-23 16:13:26 -07:00
Leonardo de Moura
da63e003e7 chore: update stage0 2022-06-23 13:32:13 -07:00
Leonardo de Moura
1e4e683e91 chore: update stage0 2022-06-23 13:30:04 -07:00
Henrik Böving
0fde2db75e feat: improve the heuristic for notation delab
Instead of the previous constraints on the right hand side that only
allowed a permutation of variables as parameters to a function the
new heuristic allows anything to the right of a function as long as
each variable only appears at most once.
2022-06-23 13:27:53 -07:00
Leonardo de Moura
3a89723f8c chore: update stage0 2022-06-23 10:23:37 -07:00
Leonardo de Moura
96a72d67f2 fix: avoid unnecessary dependencies at mkMatcher
fixes #1237
2022-06-23 10:21:32 -07:00
Leonardo de Moura
17fa60e1ec chore: remove dead code 2022-06-23 09:31:52 -07:00
Sebastian Ullrich
17c2e6d529 feat: publish fatal progress after worker crash 2022-06-23 09:24:27 -07:00
Connor Baker
c213e0e880 doc: fix overwide view when using Alectryon 2022-06-23 18:23:28 +02:00
Leonardo de Moura
939f8d9f16 fix: fixes #1240 2022-06-23 05:53:06 -07:00
Sebastian Ullrich
1f13729756 feat: show term goal at end of term as well 2022-06-23 14:44:19 +02:00
Sebastian Ullrich
13bcbce144 chore: fix Nix test output filter 2022-06-23 14:05:53 +02:00
Sebastian Ullrich
1712d0fee3 chore: update LeanInk
Resolves leanprover/LeanInk#20
2022-06-23 11:32:16 +02:00
Leonardo de Moura
108bc4c27f fix: extCore 2022-06-22 19:40:06 -07:00
Leonardo de Moura
a84b9b2e7b doc: update release notes 2022-06-22 19:34:29 -07:00
Leonardo de Moura
53acd3e355 feat: allow ext conv tactic to go inside let-declarations 2022-06-22 19:27:04 -07:00
Leonardo de Moura
4d1c6dd557 feat: add zeta conv tactic 2022-06-22 19:15:10 -07:00
Leonardo de Moura
a802544c90 fix: intro tactic at let-expr 2022-06-22 16:10:33 -07:00
Leonardo de Moura
2a940dd4ae feat: add Expr.collectFVars, LocalDecl.collectFVars, Pattern.collectFVars, and AltLHS.collectFVars
They are all in `MetaM`.

These are helper functions for issue #1237. We need to "cleanup" the
local context before trying to compile the match-expression.

see issue #1237
2022-06-22 15:53:43 -07:00
Leonardo de Moura
9678be4d81 fix: store discharge depth when caching simp results
Closes #1234
2022-06-21 15:35:47 -07:00
Leonardo de Moura
65d24f4e39 fix: typo at LinearExpr.toExpr
closes #1236
2022-06-21 14:28:26 -07:00
Sebastian Ullrich
71b99423e8 chore: Nix: fix CI 2022-06-21 23:11:57 +02:00
Sebastian Ullrich
02e5865a02 chore: Nix: stop pinning Nix in ciShell 2022-06-21 22:57:39 +02:00
Sebastian Ullrich
ce73728be3 chore: Nix: avoid build closure dependencies on stdenv 2022-06-21 21:11:59 +02:00
Sebastian Ullrich
dd58b5c2df chore: Nix: cache correct output 2022-06-21 21:10:08 +02:00
Sebastian Ullrich
e20f2e076e chore: Nix: cache lean-bin-tools 2022-06-21 20:52:39 +02:00
Leonardo de Moura
e442fbbf54 fix: remove kabstractWithPred
The function `kabstractWithPred` was never used, and introduced the
bug exposed by issue #1235.

fixes #1235
2022-06-20 16:35:18 -07:00
Leonardo de Moura
986de33097 fix: fixes #1230 2022-06-20 09:58:27 -07:00
E.W.Ayers
b6f251bcd3 fix: SubExpr.Pos.toString not terminating
fixes 1232
2022-06-19 16:04:50 -07:00
Sebastian Ullrich
58d5a11928 Revert "fix: induction: do not register _ as binder in info tree"
This reverts commit 143b2b49c8.
2022-06-18 17:24:08 +02:00
Sebastian Ullrich
99607c208c Revert "fix: intro/intros: do not register _ as binder in info tree"
This reverts commit 41dfd06e8c.
2022-06-18 17:24:08 +02:00
Sebastian Ullrich
a4236c0721 fix: ignore hygiened names in unused variables linter 2022-06-18 17:24:08 +02:00
Sebastian Ullrich
8aea00213c chore: clean up doc/flake.nix 2022-06-18 13:21:02 +02:00
Wojciech Nawrocki
7624e25de0 fix: don't duplicate tags in formatter 2022-06-18 10:07:53 +02:00
Wojciech Nawrocki
b1ef58d3cc fix: tag idents so that ofFieldInfo nodes are preserved 2022-06-18 10:07:53 +02:00
E.W.Ayers
ee6ba180ea fix: remove fix2 2022-06-17 17:47:51 -07:00
E.W.Ayers
18ba16ded9 feat: string representation of Pos
This is needed because JSON will otherwise lossily
convert big nats to floats.
2022-06-17 17:47:51 -07:00
E.W.Ayers
933964f2a4 chore: rm SubExpr.mapPos because it is not useful 2022-06-17 17:47:51 -07:00
E.W.Ayers
114bbc78ed test: numBinders 2022-06-17 17:47:51 -07:00
E.W.Ayers
8b1130c6dd test: replaceSubexpr pure p e = e
This found a bug in lensCoord which I fixed.
2022-06-17 17:47:51 -07:00
E.W.Ayers
b110d800e9 fix: add ExprTraversal to Meta 2022-06-17 17:47:51 -07:00
E.W.Ayers
4a70143aaf style: minor formatting changes 2022-06-17 17:47:51 -07:00
E.W.Ayers
3c14c97195 test: add unit test for Expr lens 2022-06-17 17:47:51 -07:00
E.W.Ayers
a7c33a963f doc: docstrings for List.isPrefixOf 2022-06-17 17:47:51 -07:00
E.W.Ayers
0707e4d442 fix: traverseChildrenWithPos bug 2022-06-17 17:47:51 -07:00
E.W.Ayers
0e84f67d99 feat: with pos expr traversal functions 2022-06-17 17:47:51 -07:00
E.W.Ayers
562070fe8b refactor: more extract methods from transform 2022-06-17 17:47:51 -07:00
E.W.Ayers
c8fc371eb9 fix: test 2022-06-17 17:47:51 -07:00
E.W.Ayers
8311c88fd0 refactor: extract methods from Lean.Meta.transform
Lean.Meta.transform is created with a series of recursive
visit functions. However these visit functions are useful
on their own outside of transform for traversing expressions.

This commit moves the visit functions outside the main function.
2022-06-17 17:47:51 -07:00
E.W.Ayers
ece1c1085c feat: add Expr lensing functions using SubExpr.Pos 2022-06-17 17:47:51 -07:00
E.W.Ayers
2fe933cdf5 refactor: make SubExpr.Pos a definition
Instead of an abbreviation. It is easier to understand
Pos operations in terms of 'push' and 'pop' rather than
through arithmetic.
2022-06-17 17:47:51 -07:00
Leonardo de Moura
bbc196eeb7 fix: make sure WF/Fix.lean tolerates MatcherApp.addArg? failures
see #1228
2022-06-17 17:37:33 -07:00
Leonardo de Moura
52a0de00e4 feat: report error on ambiguous export and open commands
This commit improves the fix for issue #1224
2022-06-17 09:58:36 -07:00
Leonardo de Moura
e985eb2b8a fix: refine resolveNamespace
see issue #1224
2022-06-17 09:51:00 -07:00
Leonardo de Moura
f0e2696ec8 doc: update release notes 2022-06-16 18:22:23 -07:00
Leonardo de Moura
81a685d97c test: issue #1224
closes #1224
2022-06-16 18:01:09 -07:00
Leonardo de Moura
a6462f5bd8 feat: improve open/export 2022-06-16 18:00:33 -07:00
Leonardo de Moura
d5476fb3b3 refactor: move toMessageList, add throwErrorWithNestedErrors 2022-06-16 18:00:09 -07:00
Leonardo de Moura
8ca3e14651 feat: change namespace resolution procedure
see #1224
2022-06-16 17:31:49 -07:00
Leonardo de Moura
d56163bd0e refactor: resolveNamespace now return a List 2022-06-16 17:16:36 -07:00
François G. Dorais
bc206b2992 fix: LawfulBEq class
make arguments implicit and protect `LawfulBEq.rfl`
2022-06-16 15:33:32 -07:00
Leonardo de Moura
8d9428261e chore: remove Fix.lean
see #1208
2022-06-16 15:30:47 -07:00
Leonardo de Moura
9e7a6fa085 chore: remove dead structure 2022-06-16 15:23:23 -07:00
Sebastian Ullrich
b1e3607739 fix: match tactic with multiple LHSs 2022-06-16 15:21:46 -07:00
Sebastian Ullrich
0777d01cf9 chore: update Lake 2022-06-16 23:33:57 +02:00
Sebastian Ullrich
72a5c582cf chore: Nix: ignore build messages in test capture 2022-06-16 23:33:57 +02:00
Sebastian Ullrich
4212cc740b refactor: move linebreak check into sepBy(1)Indent
Co-authored-by: Gabriel Ebner <gebner@gebner.org>
2022-06-16 23:33:57 +02:00
Sebastian Ullrich
6f096e0f0d chore: fix tests 2022-06-16 23:33:57 +02:00
Sebastian Ullrich
6982536108 fix: one more struct instance syntax manipulation 2022-06-16 23:33:57 +02:00
Sebastian Ullrich
0f6e6c8a51 chore: update stage0 2022-06-16 23:33:57 +02:00
Sebastian Ullrich
b585b2251e fix: adapt to stricter grammar 2022-06-16 23:33:57 +02:00
Sebastian Ullrich
ce054fb2e7 fix: introduce semicolonOrLinebreak, replace many(1) with sepBy(1) where appropriate 2022-06-16 23:33:57 +02:00
Sebastian Ullrich
7a3ee51d05 doc: missing word 2022-06-16 10:12:07 +02:00
Mariana Alanis
198179d0cc fix: add a better handling in case only worker crashes (apply CR comments) 2022-06-15 18:40:44 -07:00
Mariana Alanis
e61799a77f fix: add a better handling in case only worker crashes (CR comments) 2022-06-15 18:40:44 -07:00
Mariana Alanis
30f3d6f82d fix: add a better handling in case only worker crashes (CR comments) 2022-06-15 18:40:44 -07:00
Mariana Alanis
4d7d82af86 fix: add a better handling in case only worker crashes (CR comments) 2022-06-15 18:40:44 -07:00
Mariana Alanis
b0f9754e0f fix: add a better handling in case only worker crashes 2022-06-15 18:40:44 -07:00
Mariana Alanis
6b75ca9734 fix: add a better handlng in case only worker crashes (and server stays available) 2022-06-15 18:40:44 -07:00
Leonardo de Moura
d2888a49d7 chore: remove old hack that is not needed anymore 2022-06-15 16:36:54 -07:00
Leonardo de Moura
3228db29dd chore: use double ticks 2022-06-15 07:17:17 -07:00
Sebastian Ullrich
524ae5abf7 chore: CI: purge ccache 2022-06-15 13:39:24 +02:00
Sebastian Ullrich
23d157a3ff chore: remove dead code 2022-06-15 12:43:59 +02:00
Sebastian Ullrich
bfce841985 chore: update stage0 2022-06-15 10:01:47 +02:00
Leonardo de Moura
5896e6f1d6 chore: fix docs 2022-06-14 17:35:33 -07:00
Leonardo de Moura
540e9e85f3 chore: update release notes 2022-06-14 17:31:26 -07:00
Leonardo de Moura
989d8f04e1 chore: fix tests 2022-06-14 17:27:13 -07:00
Leonardo de Moura
f6d1e48cb8 fix: constant => opaque issues 2022-06-14 17:19:54 -07:00
Leonardo de Moura
fb55ec29e1 chore: update stage0 2022-06-14 17:14:44 -07:00
Leonardo de Moura
22c8f10b12 chore: remove constant command 2022-06-14 17:14:28 -07:00
Leonardo de Moura
02c4e548df feat: replace constant with opaque 2022-06-14 17:02:59 -07:00
Leonardo de Moura
ac33193b30 chore: update stage0 2022-06-14 16:45:20 -07:00
Leonardo de Moura
3b259afaf0 chore: fix tests 2022-06-14 16:43:22 -07:00
Leonardo de Moura
346c4beb70 feat: elaborate opaque command 2022-06-14 16:36:24 -07:00
Leonardo de Moura
794021b9e4 chore: adjust codebase
`opaque` is now a command keyword
2022-06-14 16:32:53 -07:00
Leonardo de Moura
5193c6d0ef chore: update stage0 2022-06-14 16:23:49 -07:00
Leonardo de Moura
05778565ab feat: add opaque command
It will replace the `constant` command. See
https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/What.20is.20.60opaque.60.3F/near/284926171
2022-06-14 16:22:36 -07:00
Jakob von Raumer
d7cb93e9e4 feat: allow conv mode's arg command to access implicit arguments 2022-06-14 16:15:38 -07:00
Leonardo de Moura
d78e7cd011 feat: macro expand cases and induction tactics multiple LHSs 2022-06-14 14:18:52 -07:00
Leonardo de Moura
3a1dc5e066 fix: support new inductionAlt syntax at Linter/Basic.lean 2022-06-14 11:31:49 -07:00
Leonardo de Moura
bd2cccf287 chore: use double tick 2022-06-14 11:30:55 -07:00
Leonardo de Moura
2dad133208 chore: update stage0 2022-06-14 11:26:06 -07:00
Leonardo de Moura
daeb271678 feat: update induction and cases syntax
We can now write
```
induction x with
| foo | bar => ...
| boo => ...
```

TODO: expand alternatives containing multiple LHSs.
2022-06-14 11:25:15 -07:00
Leonardo de Moura
05a72a9e00 chore: update stage0 2022-06-14 11:17:33 -07:00
Leonardo de Moura
7c9b5b7147 feat: prepare to support multi-cases at cases and induction
We want to be able to write
```
induction x with
| foo | bar => ...
| boo => ...
```
2022-06-14 11:16:58 -07:00
Sebastian Ullrich
43b08239b0 fix: further conv goal state refinements 2022-06-14 11:09:47 +02:00
Sebastian Ullrich
7bb94abb62 feat: trace.Elab.input
Unlike Elab.command, it does not contain macro expansions
2022-06-14 10:41:56 +02:00
Leonardo de Moura
77ae79be46 chore: use let/if in do blocks 2022-06-13 17:10:14 -07:00
Leonardo de Moura
7dbdfa090a chore: remove debugging leftovers 2022-06-13 16:37:31 -07:00
E.W.Ayers
13e286f545 doc: fix docstring for InteractiveGoal 2022-06-13 16:32:01 -07:00
E.W.Ayers
2edf02544e chore: rm ExprWithCtx
We will make this a separate PR
2022-06-13 16:32:01 -07:00
E.W.Ayers
367bde3601 chore: revert "refactor: replace InfoWithCtx with ExprWithCtx"
This reverts commit db342793d5.
2022-06-13 16:32:01 -07:00
E.W.Ayers
f64cb95eca refactor: replace InfoWithCtx with ExprWithCtx
This is potentially controversial. There are still some [todo]s that need sorting.
2022-06-13 16:32:01 -07:00
E.W.Ayers
3d561a3ab0 doc: add docstrings for interactive 2022-06-13 16:32:01 -07:00
E.W.Ayers
e3d2080232 refactor: PPExprTaggedRequest -> PPExprTaggedParams 2022-06-13 16:32:01 -07:00
E.W.Ayers
fd66e70d1e fix: explicit structure for PPExprTaggedRequest 2022-06-13 16:32:01 -07:00
E.W.Ayers
69facfbe8e fix: remove Optional from InteractiveHypothesisBundle.fvarIds 2022-06-13 16:32:01 -07:00
E.W.Ayers
45e3c72be7 refactor: InteractiveHypothesis → InteractiveHypothesisBundle 2022-06-13 16:32:01 -07:00
Ed Ayers
5130da82a8 doc: src/Lean/Widget/InteractiveGoal.lean
Co-authored-by: Sebastian Ullrich <sebasti@nullri.ch>
2022-06-13 16:32:01 -07:00
E.W.Ayers
cea53fc53e fix: tests
Caused by a classic imperative programming bug oops
2022-06-13 16:32:01 -07:00
E.W.Ayers
f2a874ebaa fix: handle inaccessible fvar names correctly 2022-06-13 16:32:01 -07:00
E.W.Ayers
675147dcfc fix: make InteractiveHyp.fvarIds optional
This is for backwards compat.
2022-06-13 16:32:01 -07:00
E.W.Ayers
0f61d1dc59 refactor: key fields are now f/mvarid fields 2022-06-13 16:32:01 -07:00
E.W.Ayers
4165b7e8ba doc: ToHide.collect 2022-06-13 16:32:01 -07:00
E.W.Ayers
6e1c9653d9 feat: Add a key field to InteractiveGoal
This is used to uniquely identify InteractiveGoals and
InteractiveHypotheses. This makes it easier to do
contextual suggestions: eg the infoview can send a message
saying "the user clicked on subexpression 5 in hypothesis N in goal G"
where N and G are unique identifiers for a goal rather than pretty names
which may be non-unique or indices which may be difficult to compute
(eg in infoview there is a mode where hypotheses are reversed or filtered).

While adding these I also refactored the InteractiveGoal generating function.
I unwrapped a fold in to a for/in loop with mutating variables which is a
little easier to read.
2022-06-13 16:32:01 -07:00
Wojciech Nawrocki
351be06a21 feat: ppExprTagged RPC call 2022-06-13 16:32:01 -07:00
Wojciech Nawrocki
4972f214be fix: sorried errors in rpcServerMethod 2022-06-13 16:32:01 -07:00
Leonardo de Moura
c2fdcad443 chore: update stage0 2022-06-13 16:23:53 -07:00
Leonardo de Moura
e52a7bdf42 feat: let/if indentation in do blocks
closes #1120
2022-06-13 16:18:49 -07:00
Leonardo de Moura
415f5f2a42 chore: style 2022-06-13 15:59:55 -07:00
Leonardo de Moura
dee712ec7e chore: fix test
Pushed the wrong file in previous commit.

see #490
2022-06-13 14:06:56 -07:00
Leonardo de Moura
9ba5831de8 fix: _root_ prefix in declarations
closes #490
2022-06-13 14:03:18 -07:00
Leonardo de Moura
328586988c chore: style 2022-06-13 13:58:29 -07:00
Sebastian Ullrich
bda871da25 feat: RBTree.union/diff 2022-06-13 11:12:51 +02:00
Leonardo de Moura
fb574af873 fix: mkSplitterProof
This commit fixes the first issue reported at #1179

closes #1179
2022-06-12 19:38:54 -07:00
Wojciech Nawrocki
46257dfb0e feat: show bitwise terminates 2022-06-12 14:01:05 -07:00
Wojciech Nawrocki
4d05803782 feat: WF lemma for Nat division 2022-06-12 14:01:05 -07:00
Wojciech Nawrocki
2a53857928 feat: add strong Nat induction principle 2022-06-12 14:01:05 -07:00
Wojciech Nawrocki
ff15e31e85 refactor: remove redundant theorem 2022-06-12 14:01:05 -07:00
Leonardo de Moura
09d1530d8e feat: detect unexpected occurrences of match-expression minor premises
The error message is far from perfect, but it is better than ignoring
the issue and failing later with an even more incomprehensible error
message.

see #1179
2022-06-12 12:07:42 -07:00
Leonardo de Moura
8a8a8b5e48 chore: style 2022-06-10 18:27:43 -07:00
Jakob von Raumer
033618ad5e fix: indices in conv arg now count arguments with forward dependencies 2022-06-10 18:25:34 -07:00
Leonardo de Moura
17db981880 fix: equation theorem for match with more than one "as" pattern
see #1195
see #1179
2022-06-10 18:23:13 -07:00
tydeu
78c57161d8 chore: update Lake 2022-06-10 17:50:05 -07:00
Leonardo de Moura
4ba7174c0c fix: universe level parameter stabilitity issue
See comment.
2022-06-10 14:08:08 -07:00
Sebastian Ullrich
67087ac16e fix: bad reassignment 2022-06-10 18:28:31 +02:00
Sebastian Ullrich
efff36d3e9 chore: update stage0 2022-06-10 18:17:57 +02:00
Sebastian Ullrich
61232e788a fix: check types at do pattern reassignment 2022-06-10 17:31:36 +02:00
Sebastian Ullrich
a44fec2262 chore: CI: exclude test harder 2022-06-10 12:02:23 +02:00
Sebastian Ullrich
8c377436f4 fix: do not report unused variables in unfinished declarations 2022-06-10 11:27:11 +02:00
Sebastian Ullrich
45636324f9 chore: CI: exclude nonreproducible test 2022-06-10 11:12:09 +02:00
Leonardo de Moura
97e689d670 chore: add link from Lean 4 manual to FP in Lean 2022-06-09 16:28:54 -07:00
Leonardo de Moura
0ac863b353 chore: add link to the new book 2022-06-09 16:09:07 -07:00
Sebastian Ullrich
41dfd06e8c fix: intro/intros: do not register _ as binder in info tree
Fixes #1204
2022-06-09 15:23:56 +02:00
Chris Lovett
33159b51e5 chore: build integration with TPIL 2022-06-09 09:23:04 +02:00
Leonardo de Moura
d0499ebf4d fix: fixes #1200 2022-06-08 10:18:05 -07:00
Leonardo de Moura
fa64c072ab feat: where declarations at instances
https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/Local.20functions.20in.20instances/near/285333999
2022-06-07 18:48:15 -07:00
Leonardo de Moura
0c28d4ff4d chore: update stage0 2022-06-07 18:42:16 -07:00
Leonardo de Moura
1e59eb2290 chore: update whereStructInst 2022-06-07 18:41:43 -07:00
Leonardo de Moura
ce78c17f2d chore: update stage0 2022-06-07 17:54:42 -07:00
Leonardo de Moura
041827bed5 chore: unused variables 2022-06-07 17:54:10 -07:00
Leonardo de Moura
a18c78e617 chore: update stage0 2022-06-07 16:48:55 -07:00
Leonardo de Moura
c2ddebc193 chore: unused variables 2022-06-07 16:47:04 -07:00
Sebastian Ullrich
130cc8bbd5 chore: fix test 2022-06-07 16:37:45 -07:00
Sebastian Ullrich
f9e2a65f75 chore: further cleanup
Co-authored-by: Gabriel Ebner <gebner@gebner.org>
2022-06-07 16:37:45 -07:00
Sebastian Ullrich
8eefbf5227 chore: further clean up refactored code 2022-06-07 16:37:45 -07:00
Sebastian Ullrich
897a5de6ac chore: revert some questionable signature changes 2022-06-07 16:37:45 -07:00
Sebastian Ullrich
fb2a2b3de2 fix: fixup previous commit 2022-06-07 16:37:45 -07:00
Sebastian Ullrich
ae7b895f7a refactor: unname some unused variables 2022-06-07 16:37:45 -07:00
Sebastian Ullrich
8ffa07ab25 fix: goal state on conv => 2022-06-07 17:43:16 +02:00
Sebastian Ullrich
a07e9df66e fix: use goal prefix in plain goal response 2022-06-07 17:42:09 +02:00
Sebastian Ullrich
388ed62858 chore: update Alectryon 2022-06-07 17:14:41 +02:00
Chris Lovett
885deec745 doc: add link to short quickstart video 2022-06-06 18:32:11 -07:00
Leonardo de Moura
09ddf76029 feat: simp_all now uses dependent hypotheses for simplification
However, it does not simplify them.

closes #1194
2022-06-06 18:31:34 -07:00
Leonardo de Moura
875e71a0d7 chore: unused variables at Simp.lean 2022-06-06 18:24:10 -07:00
Leonardo de Moura
71226243fd fix: fixes #1192 2022-06-06 18:20:45 -07:00
Leonardo de Moura
0f111da64c chore: unused variables at Inductive.lean 2022-06-06 18:15:25 -07:00
Leonardo de Moura
5055855637 feat: improve default simp discharge method
closes #1193
2022-06-06 17:29:12 -07:00
Leonardo de Moura
3d04899e42 refactor: add unifyEq? 2022-06-06 15:53:40 -07:00
Leonardo de Moura
c9c9b8d835 chore: avoid code duplication 2022-06-06 15:53:40 -07:00
Leonardo de Moura
7dab01be1b chore: unused eqns 2022-06-06 15:53:40 -07:00
Leonardo de Moura
2832442e7a fix: unfold declarations tagged with [matchPattern] at reduceMatcher? even if transparency setting is not the default one
see #1193

It fixes one of the issues exposed at the issue above.
2022-06-06 15:53:40 -07:00
Leonardo de Moura
e24483d6d3 doc: expand isGenDiseq comment 2022-06-06 15:53:40 -07:00
larsk21
60c8a72262 fix: unused variables linter: consider induction variables as pattern variables 2022-06-06 15:53:10 -07:00
larsk21
a9293410a2 fix: unused variables linter: ignore structure, class and inductive signatures 2022-06-06 15:53:10 -07:00
Wojciech Nawrocki
5b13a4909b doc: fix transform docstring 2022-06-06 23:06:47 +02:00
Sebastian Ullrich
143b2b49c8 fix: induction: do not register _ as binder in info tree 2022-06-06 23:05:12 +02:00
E.W.Ayers
d55daf80d4 doc: fix misleading SubExpr docstring 2022-06-06 09:37:51 -07:00
Leonardo de Moura
d00d8a2104 fix: typo at copyDefaultValue?
see #1190
2022-06-06 07:57:23 -07:00
Leonardo de Moura
22281f25c8 fix: typo at sameHeadSymbol
see #1190
2022-06-06 07:46:57 -07:00
Sebastian Ullrich
7428dc5e71 Revert "chore: CI: use publish-unit-test-result-action"
Was just an experiment, its benefit is negligible

This reverts commit 3575981ee6.
2022-06-05 14:23:20 +02:00
Sebastian Ullrich
3c41962275 refactor: Expr.forEach' use in unused variables linter 2022-06-05 14:16:40 +02:00
Sebastian Ullrich
85e0e0ad20 doc: fix Expr.forEach' docstring 2022-06-05 14:16:29 +02:00
Sebastian Ullrich
3575981ee6 chore: CI: use publish-unit-test-result-action 2022-06-05 14:10:17 +02:00
Sebastian Ullrich
7870c24cdd chore: update stage0 2022-06-04 13:57:39 +02:00
Sebastian Ullrich
ec045bfbb8 feat: $_ antiquotation pattern 2022-06-04 13:57:04 +02:00
Sebastian Ullrich
a65197bb78 doc: update changelog 2022-06-03 22:58:38 +02:00
Sebastian Ullrich
05c5dd4441 fix: unused variables linter: search fvar aliases in tactics 2022-06-03 22:37:38 +02:00
Sebastian Ullrich
f3a7654a63 fix: unused variables linter: find nested uses in tactics 2022-06-03 22:37:38 +02:00
E.W.Ayers
1785ab142e refactor: move Lean.PrettyPrinter.Delaborator.SubExpr to Lean.SubExpr
This is because SubExpr has uses outside the Delaborator.

Closes #1183
2022-06-03 12:38:14 -07:00
Sebastian Ullrich
a0624ec296 chore: CI: ignore foreigntest on Linux release 2022-06-03 17:04:06 +02:00
Leonardo de Moura
9d6b67eae2 fix: remove check from Simp.synthesizeArgs
Some `simp` dischargers can handle metavariables (e.g,
`assumption`). See new test.

closes #1184
2022-06-03 07:40:30 -07:00
Sebastian Ullrich
3cfbdd134a fix: update Alectryon 2022-06-03 16:05:59 +02:00
Sebastian Ullrich
0b264889ae fix: goal state on ; after · 2022-06-03 13:41:04 +02:00
Sebastian Ullrich
d15934c0ac chore: Nix: Bring-Your-Own-Emacs .#emacs-path-dev 2022-06-03 13:41:04 +02:00
Sebastian Ullrich
cfa14b3ce0 chore: nix flake update 2022-06-03 13:41:04 +02:00
larsk21
caa8804a1d feat: add nolint options for function arguments and pattern variables 2022-06-03 13:03:52 +02:00
larsk21
93480a3e05 fix: consider tactic mvar assignments for used variables 2022-06-03 13:03:52 +02:00
larsk21
bf907d7b8c fix: ignore exposed function arguments in unused variables linter 2022-06-03 13:03:52 +02:00
larsk21
57c8c76cd0 fix: use findModuleRefs in unused variables linter 2022-06-03 13:03:52 +02:00
larsk21
b556e73657 refactor: extend Lsp.ModuleRefs in Server.References 2022-06-03 13:03:52 +02:00
larsk21
cf4e106304 fix: unused variables linter review comments
- ignore unused variables in dep arrows
- avoid negated options
- make syntax stack generation more performant
- make ignore functions more extensible
- change message severity to `warning`
2022-06-03 13:03:52 +02:00
larsk21
b708eaec2c fix: forward lean options to workers 2022-06-03 13:03:52 +02:00
larsk21
393fdef972 fix: disable linters in tests 2022-06-03 13:03:52 +02:00
larsk21
37d5f8e74a feat: add unused variables linter 2022-06-03 13:03:52 +02:00
larsk21
8824a479a5 fix: add additional information to Lean.Server.Reference 2022-06-03 13:03:52 +02:00
larsk21
1a1f8f52a5 fix: run linters after elaboration 2022-06-03 13:03:52 +02:00
Leonardo de Moura
8649483b41 feat: produces an error if the declaration body contains a universe parameter that does not occur in the declaration type nor is explicitly provided
closes #898
2022-06-02 19:43:09 -07:00
Leonardo de Moura
484e510221 feat: do not use pp.inaccessibleNames = true at getInteractiveTermGoal
See discussion at https://github.com/leanprover/vscode-lean4/issues/76

We also use `pp.inaccessibleNames = false` in error messages. In this
setting, an inaccessible name is displayed in the context only if the
target type depends on it.
2022-06-02 16:22:43 -07:00
Leonardo de Moura
878ef3a281 feat: improve acyclic tactic
closes #1182
2022-06-02 15:25:14 -07:00
Sebastian Ullrich
1fff412b1f fix: regressions from previous commit 2022-06-02 19:04:47 +02:00
Sebastian Ullrich
ddfbf6bf9b fix: show namespace when hovering over declaration name 2022-06-02 18:17:21 +02:00
Leonardo de Moura
32db316166 fix: enumeration type noConfusion was not registered
This commit fixes issue reported at
https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/.28kernel.29.20function.20expected.20.2EnoConfusion/near/284634050
2022-06-01 17:58:46 -07:00
Gabriel Ebner
9a273b85a3 fix: no sorry-warning for missing match cases 2022-06-01 07:41:52 -07:00
Leonardo de Moura
bf0b675ca6 chore: fix tests 2022-06-01 06:36:25 -07:00
Leonardo de Moura
9102f8cb13 fix: generate sorry warning only if there are no error messages
see #1163
2022-06-01 06:32:05 -07:00
Leonardo de Moura
9290a0e9b1 chore: fix tests 2022-05-31 18:17:56 -07:00
Leonardo de Moura
ac440e757d chore: update stage0 2022-05-31 18:14:05 -07:00
Leonardo de Moura
5302267220 test: for #1163 2022-05-31 18:09:27 -07:00
Leonardo de Moura
2e6dae01f0 chore: synthetic := false by default at sorryAx 2022-05-31 18:08:10 -07:00
Leonardo de Moura
2b2f315fb9 chore: fix tests 2022-05-31 18:01:48 -07:00
Leonardo de Moura
64c36fffda feat: generate warning message if declaration has a non-synthetic sorry
closes #1163
2022-05-31 18:00:48 -07:00
Leonardo de Moura
0631c90794 feat: implement MonadLog at CoreM 2022-05-31 17:40:55 -07:00
Leonardo de Moura
caa79ca04f refactor: move MonadLog 2022-05-31 16:50:48 -07:00
Leonardo de Moura
be69d04af4 feat: add Declaration.hasSorry 2022-05-31 16:39:37 -07:00
Leonardo de Moura
5f7cc78f17 fix: remove unnecessary let-expressions when computing the motive
fixes #1155
2022-05-31 07:14:56 -07:00
Leonardo de Moura
704242f865 feat: zetaReduce should expand nested let-expressions too 2022-05-31 07:01:52 -07:00
Leonardo de Moura
d8aab852e8 feat: add usedLetOnly parameter to Meta.transform 2022-05-31 07:00:53 -07:00
Leonardo de Moura
e997cd94c6 chore: style 2022-05-31 06:04:48 -07:00
larsk21
a741540400 fix: relax InfoTree.visitM when visiting holes 2022-05-31 13:14:24 +02:00
Wojciech Nawrocki
115c564b18 feat: go to head constant in applications
Co-authored-by: Sebastian Ullrich <sebasti@nullri.ch>
2022-05-31 00:07:56 +02:00
Wojciech Nawrocki
737e872ee0 feat: set tagAppFns in explicit exprToInteractive 2022-05-31 00:07:56 +02:00
Wojciech Nawrocki
9c9407e722 feat: propagate tagAppFns in delaborator 2022-05-31 00:07:56 +02:00
Wojciech Nawrocki
cd47c30e47 chore: review fixes 2022-05-31 00:07:56 +02:00
Wojciech Nawrocki
8c67afae2f feat: generalize getGoToLocation RPC 2022-05-31 00:07:56 +02:00
Wojciech Nawrocki
8c5cebfb11 chore: default optional LSP fields 2022-05-31 00:07:56 +02:00
Wojciech Nawrocki
aef8d32d0b feat: add RPC call to retrieve defn/decl/type defn 2022-05-31 00:07:56 +02:00
Wojciech Nawrocki
9c058a5798 chore: remove some unnecessary partial 2022-05-31 00:07:56 +02:00
Wojciech Nawrocki
e555490ee2 feat: store subexpression positions 2022-05-31 00:07:56 +02:00
Wojciech Nawrocki
25a8646a5f feat: add showDocument client capability 2022-05-31 00:07:56 +02:00
ammkrn
102e957bb5 feat: support proofs in deriving DecidableEq
The derive handler for `DecidableEq` does not currently support proofs
in constructor arguments/structure fields. For example, deriving
`DecidableEq` for `Fin n` will fail, because of the field `isLt`. This
change checks whether the elements being tested are proofs, and if so,
changes the equality proof to just `rfl`.
2022-05-30 07:36:30 -07:00
Leonardo de Moura
9818de078b fix: fixes #1168 2022-05-30 07:24:23 -07:00
Leonardo de Moura
fb45eb4964 fix: universe polymorphic enumeration types
Fixes issue reported at https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/Incorrect.20number.20of.20universe.20levels.20parameters/near/284283021
2022-05-30 06:43:46 -07:00
Leonardo de Moura
b0efae4823 chore: style 2022-05-30 06:43:46 -07:00
Sebastian Ullrich
ef9976ccda fix: do not discard macro exceptions in expandMacro? 2022-05-30 13:28:42 +02:00
Sebastian Ullrich
d3cf60e86a chore: further refine goal state heuristics 2022-05-30 13:27:56 +02:00
Sebastian Ullrich
b31690b1d7 fix: go to definition/goal state at end of syntax 2022-05-30 11:16:25 +02:00
Leonardo de Moura
ca6f53b407 feat: use subst_vars at builtin decreasing_tactic 2022-05-28 16:24:32 -07:00
Leonardo de Moura
6dc728cc60 chore: update stage0 2022-05-28 16:20:23 -07:00
Leonardo de Moura
40fc64480a feat: add tactic subst_vars 2022-05-28 16:19:34 -07:00
Leonardo de Moura
2c5bafcbd8 fix: dead variables at match equation hypotheses
This commit addresses an issue reported at https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/Structural.20Recursion.20Problem/near/284238723
2022-05-28 16:09:35 -07:00
Leonardo de Moura
e26f86dd45 fix: improve simpH?, remove unnecessary hypotheses 2022-05-28 15:30:01 -07:00
Leonardo de Moura
34bbe5d12c feat: add simp theorem List.of_toArray_eq_toArray (as bs : List α) : (as.toArray = bs.toArray) = (as = bs) := by 2022-05-27 18:26:48 -07:00
Leonardo de Moura
fbd8224b4d fix: allow recursive occurrences in binder types at WF/PackDomain.lean
fixes #1171
2022-05-27 11:23:51 -07:00
Leonardo de Moura
3be437cad3 fix: make sure register_simp_attr declares an simp-like attribute parser for user simp attributes
closes #1164
2022-05-26 19:49:33 -07:00
Leonardo de Moura
7d8f8c0fbe chore: style 2022-05-26 15:18:07 -07:00
Leonardo de Moura
25126cd057 fix: autoParam is structure fields lost in multiple inheritance
closes #1158
2022-05-26 14:35:47 -07:00
Leonardo de Moura
b4c1163f8f chore: update stage0 2022-05-26 14:22:38 -07:00
Leonardo de Moura
f48b822532 feat: add field for storing autoParam information at StructureFieldInfo
We need this information when copying fields from parent structures.
We don't use hacks such as traversing the parent constructor type.
2022-05-26 14:21:03 -07:00
Leonardo de Moura
dcb974a1cf chore: remove unused parameter 2022-05-26 14:20:51 -07:00
Leonardo de Moura
fc606f3ab5 fix: closes #1156 2022-05-26 12:51:28 -07:00
Leonardo de Moura
988697b431 fix: fixes #1169 2022-05-26 07:05:32 -07:00
Leonardo de Moura
1d14637680 fix: missing withMVarContext 2022-05-26 06:18:14 -07:00
Leonardo de Moura
fad21a4cda chore: remove leftovers 2022-05-25 20:38:20 -07:00
Leonardo de Moura
944063682e fix: another specialize.cpp bug
This is just a workaround. This code has to be ported to Lean.

The issue has been reported at https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/.28kernel.29.20unknown.20constant/near/283750650
2022-05-25 20:36:18 -07:00
Leonardo de Moura
dca8a8ed98 fix: match or-pattern
This issue has been reported at
https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/Probably.20a.20bug/near/283779934
2022-05-25 20:05:46 -07:00
Leonardo de Moura
bef1cd4872 fix: make structure instance notation (e.g., { a, b }) works in patterns after we define the Set notation in Mathlib 2022-05-25 19:14:22 -07:00
Leonardo de Moura
a26827f58b chore: remove Context.main 2022-05-25 11:58:33 -07:00
Jannis Limperg
6dc5ddac35 fix: apply after-compilation attributes to inductive/structure decls
Attributes with `AttributeApplicationTime.afterCompilation` were
silently not applied to `inductive` and `structure` declarations.
2022-05-25 11:32:08 -07:00
Sebastian Ullrich
4a1885f997 chore: update benchmark suite 2022-05-25 18:26:36 +02:00
asdasd1dsadsa
794877c0c8 chore: add option to exclude 'LICENSE' files from 'make install' 2022-05-25 12:39:30 +02:00
Sebastian Ullrich
b97fb23dbe chore: update stage0 2022-05-25 09:48:11 +02:00
Sebastian Ullrich
0a39e9cbdc fix: dynamic quotations should use previous stage by default
@leodemoura as discussed some time ago
2022-05-25 09:46:10 +02:00
Leonardo de Moura
cb32681978 doc: add slide headers to examples 2022-05-23 18:20:37 -07:00
Leonardo de Moura
bf5f107e74 doc: missing NFM examples 2022-05-23 18:04:03 -07:00
Leonardo de Moura
7c427c1ef2 fix: make sure let-expressions do not affect the structural recursion module
This issue has been reported at https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/Termination.20check.20not.20preserved.20under.20let.20binding.2E/near/282934378
2022-05-23 13:42:48 -07:00
Leonardo de Moura
655c9fafa4 chore: update stage0 2022-05-23 12:00:10 -07:00
Leonardo de Moura
d05dff078a chore: update stage0 2022-05-23 11:56:59 -07:00
Leonardo de Moura
2fc23a2a2b feat: make sure we can use split to synthesize code 2022-05-23 11:55:57 -07:00
Leonardo de Moura
e552558f2f chore: style 2022-05-23 11:04:29 -07:00
Leonardo de Moura
6ce6b12707 doc: NFM'22 examples 2022-05-22 19:21:30 -07:00
Leonardo de Moura
56cd6c1ff5 fix: we should not use implicit targets when creating the key for the CustomEliminator map 2022-05-20 06:55:23 -07:00
Leonardo de Moura
063c77037f chore: fix typo 2022-05-20 06:44:25 -07:00
E.W.Ayers
8ef0154403 refactor: rpc -> serverRpcMethod 2022-05-19 18:53:19 +02:00
E.W.Ayers
3bdb98e5ee feat: rpc attribute
Functions can now be marked with the `@[rpc]` attribute, which
registers the function as an RpcProcedure that can be used to
communicate with the code editor and infoview.
2022-05-19 18:53:19 +02:00
Sebastian Ullrich
d13fac6f45 doc: update quickstart 2022-05-18 17:43:14 +02:00
Sebastian Ullrich
c3a9831388 doc: document ‹t› 2022-05-18 10:32:06 +02:00
Sebastian Ullrich
1d44c30b3f refactor: simplify log2 termination proof 2022-05-18 10:20:36 +02:00
Sebastian Ullrich
eb170d1f43 fix: compiled string literals containing null bytes 2022-05-17 09:24:34 -07:00
Sebastian Ullrich
1e271c3432 chore: CI: document ridiculous workaround 2022-05-17 17:45:58 +02:00
Sebastian Ullrich
14225b81ce chore: CI: really? 2022-05-17 15:53:33 +02:00
Sebastian Ullrich
a2bf2a4abd fix: info at pattern variables 2022-05-17 06:28:59 -07:00
Sebastian Ullrich
61c7b8b94c chore: format string 2022-05-16 15:14:01 +02:00
Sebastian Ullrich
46df02877d fix: elab info for decreasing_by 2022-05-16 10:20:49 +02:00
Sebastian Ullrich
bfb9dc0697 chore: CI: really do not build nightlies on forks 2022-05-16 09:58:26 +02:00
Sebastian Ullrich
4934104eaf chore: update script/reformat.lean 2022-05-13 11:55:44 +02:00
Wojciech Nawrocki
5cd4bd3552 refactor: auto-derive RpcEncoding 2022-05-12 13:22:37 -07:00
Wojciech Nawrocki
a8cfbb11bf Revert "chore: fix tests"
This reverts commit c6acd968d7.
2022-05-12 13:22:37 -07:00
Wojciech Nawrocki
c81ee908ea chore: update stage0 2022-05-12 13:22:37 -07:00
Wojciech Nawrocki
bea68819c9 feat: support optional RPC fields 2022-05-12 13:22:37 -07:00
Wojciech Nawrocki
dd6528bceb fix: undo incorrect JSON encoding 2022-05-12 13:22:37 -07:00
Leonardo de Moura
f1e9ed2e5a chore: update stage0 2022-05-12 08:48:57 -07:00
Leonardo de Moura
c6acd968d7 chore: fix tests 2022-05-12 08:44:00 -07:00
Leonardo de Moura
9460078dd1 chore: update stage0 2022-05-12 08:39:27 -07:00
Sebastian Ullrich
4e3ddf716e refactor: unnecessary quotation kind 2022-05-12 08:38:09 -07:00
Sebastian Ullrich
75cbb5904e refactor: use syntax quotations 2022-05-12 08:38:09 -07:00
Wojciech Nawrocki
7ad1ccab78 feat: use quotation prechecks where possible at FromToJson 2022-05-12 08:38:09 -07:00
Wojciech Nawrocki
9296afca12 chore: undo unnecessary change 2022-05-12 08:38:09 -07:00
Wojciech Nawrocki
fbb20d465b fix: RpcEncoding tests 2022-05-12 08:38:09 -07:00
Wojciech Nawrocki
603a062f1f chore: revert API change 2022-05-12 08:38:09 -07:00
Wojciech Nawrocki
63b33424e1 feat: add Widget.Basic 2022-05-12 08:38:09 -07:00
Wojciech Nawrocki
460abc4b94 fix: failure in FromToJson 2022-05-12 08:38:09 -07:00
Wojciech Nawrocki
0b554f385e feat: RpcEncoding for inductive types 2022-05-12 08:38:09 -07:00
Wojciech Nawrocki
c291a78b6a fix: repeated field types in RpcEncoding 2022-05-12 08:38:09 -07:00
Wojciech Nawrocki
a19c666f2d feat: add helpers 2022-05-12 08:38:09 -07:00
Wojciech Nawrocki
100008ceb1 feat: support generic structure parameters in RpcEncoding 2022-05-12 08:38:09 -07:00
Wojciech Nawrocki
72c4717055 chore: remove dead code 2022-05-12 08:38:09 -07:00
Wojciech Nawrocki
11e10459bb refactor: move function to PrettyPrinter 2022-05-12 08:38:09 -07:00
Wojciech Nawrocki
81b1f1df6e refactor: unify format functions 2022-05-12 08:38:09 -07:00
Wojciech Nawrocki
aa2ad384e7 chore: remove old InfoTree ctor 2022-05-12 08:38:09 -07:00
Wojciech Nawrocki
b33eb12328 chore: simplify evaluation and use macro scope instead of namespace 2022-05-12 08:38:09 -07:00
Wojciech Nawrocki
aa5fe5864a doc: document some Deriving utils 2022-05-12 08:38:09 -07:00
Wojciech Nawrocki
4b3c2b1790 doc: document some meta utilities 2022-05-12 08:38:09 -07:00
Leonardo de Moura
a8032e4173 fix: another mut misbehaving example
```
def mutVariableDo2 (list : List Nat) : Nat := Id.run <| do
  let mut sum := 0
  for _ in list do
    sum := sum.add 1  -- first `sum` was not connected, i.e., it was not highlighted when hovering over the second `sum`
  pure sum
```
2022-05-12 08:26:07 -07:00
Leonardo de Moura
362961912b chore: remove unnecessary variable 2022-05-12 06:44:13 -07:00
Leonardo de Moura
f44a701637 chore: style 2022-05-11 15:32:18 -07:00
Sebastian Ullrich
d03f0b3851 fix: set of chained lexical references 2022-05-11 17:32:06 +02:00
Sebastian Ullrich
23fac14b33 chore: try with fresh cache 2022-05-11 12:31:55 +02:00
Leonardo de Moura
94d2a3ef86 feat: improve error message when failing to infer resulting universe level for inductive datatypes and structures 2022-05-10 18:30:53 -07:00
Leonardo de Moura
c935a3ff6a feat: improve error location for universe level errors at inductive command 2022-05-10 12:50:01 -07:00
Sebastian Ullrich
392640d292 feat: allow keyword-like projection identifiers 2022-05-10 12:25:30 -07:00
Leonardo de Moura
37b2f74404 chore: update stage0 2022-05-10 11:24:10 -07:00
Leonardo de Moura
1d066364f3 chore: update stage0 2022-05-10 11:21:54 -07:00
Leonardo de Moura
f58afaaa43 fix: make sure let _ := val and let _ : type := val are treated at letIdDecl
closes #1114
2022-05-10 06:52:27 -07:00
Sebastian Ullrich
1b51bab4a1 feat: turn on info trees by default 2022-05-10 06:24:31 -07:00
Leonardo de Moura
7ce0471f28 feat: improve binrel% elaborator
It now relies on `binop%` too, and addresses issue reported at
https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/Regression.20in.20coercion.20inference/near/281737387
2022-05-09 18:39:52 -07:00
Leonardo de Moura
1768067aa0 doc: document elaboration issue
described at
https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/Regression.20in.20coercion.20inference/near/281737387

TODO: improve `binrel%` elaboration function.
2022-05-09 17:39:24 -07:00
Sebastian Ullrich
ff6537be1b fix: use consistent goal prefix everywhere 2022-05-09 17:49:00 +02:00
Leonardo de Moura
fc03b2fc31 feat: unfold ident,+ 2022-05-09 07:09:53 -07:00
Leonardo de Moura
2680711f6a chore: update stage0 2022-05-09 07:09:53 -07:00
Leonardo de Moura
995d4f0979 chore: prepare for unfold ident,+ 2022-05-09 07:09:22 -07:00
Leonardo de Moura
e729b32b2b feat: unfold should fail if it didn't unfold anything 2022-05-09 06:41:17 -07:00
Leonardo de Moura
4875224bd4 feat: unfold tactic tries to reduce match after unfolding 2022-05-09 06:35:40 -07:00
Leonardo de Moura
ecbc59c8d8 chore: split Notation.lean 2022-05-09 05:20:19 -07:00
Sebastian Ullrich
fa7c35f4f6 doc: normalize tactic doc strings 2022-05-09 10:37:59 +02:00
William Blake
9c72917f5e doc: fix typo gree -> tree 2022-05-09 09:44:48 +02:00
Leonardo de Moura
3cd46888bf fix: check types using default reducibility at synthInstance?
closes #1131
2022-05-08 06:49:14 -07:00
Leonardo de Moura
0fd47fd817 chore: update stage0 2022-05-07 15:52:01 -07:00
Sebastian Ullrich
91991649bc fix: connect occurrences of mutable variable inside and outside for in info tree 2022-05-07 15:50:26 -07:00
Sebastian Ullrich
22f8ea147c fix: propagate position information of variables in do blocks 2022-05-07 15:50:26 -07:00
Sebastian Ullrich
daa9e03e78 fix: combineFvars 2022-05-07 15:50:26 -07:00
Sebastian Ullrich
2f461d201e fix: info tree of let_delayed 2022-05-07 15:50:26 -07:00
François G. Dorais
155b41937a fix: remove unnecessary hypothesis (#1144) 2022-05-07 15:39:37 -07:00
Leonardo de Moura
9043f91d8c fix: if Tactic.Context.recover == false, we must disable "error to sorry" when elaborating terms in tactics
closes #1142
2022-05-07 15:37:12 -07:00
Leonardo de Moura
ab31f9ad5d fix: fixes #1143 2022-05-07 15:27:34 -07:00
Leonardo de Moura
dc1b16c4fb chore: update stage0 2022-05-07 15:10:06 -07:00
Leonardo de Moura
2c8c20d424 feat: add [eliminator] attribute specifying default recursors/eliminators for the cases and induction tactics 2022-05-07 15:09:42 -07:00
Leonardo de Moura
73cb952275 feat: add Hashable (Array α) instance 2022-05-07 15:01:32 -07:00
Leonardo de Moura
b5bcf252ce chore: cleanup 2022-05-07 14:48:22 -07:00
Leonardo de Moura
af5e13e534 feat: improve binop% elaboration function 2022-05-07 10:32:55 -07:00
Leonardo de Moura
38baeaf373 feat: backtrack when applying default instances if subproblems cannot be solved 2022-05-07 09:56:38 -07:00
Leonardo de Moura
8c23bef399 feat: add support for casesOn applications to structural and well-founded recursion modules 2022-05-06 17:12:10 -07:00
Leonardo de Moura
090503cfd5 chore: cleanup 2022-05-06 17:12:10 -07:00
KaseQuark
5ebd6c28db feat: change "⊢" in conv goals to "|" 2022-05-06 09:35:04 +02:00
Leonardo de Moura
7a1c79043e chore: fix test 2022-05-04 15:34:37 -07:00
Leonardo de Moura
dce92c6362 chore: update stage0 2022-05-04 15:32:22 -07:00
Leonardo de Moura
db89750030 chore: update RELEASES.md 2022-05-04 15:31:57 -07:00
Leonardo de Moura
5aaccc8ebb chore: remove OptionM 2022-05-04 15:30:10 -07:00
Leonardo de Moura
eaea5c4773 chore: update stage0 2022-05-04 15:28:49 -07:00
Leonardo de Moura
c65537aea5 feat: Option is a Monad again
TODO: remove `OptionM` after update stage0

see: https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/Do.20we.20still.20need.20OptionM.3F/near/279761084
2022-05-04 15:27:42 -07:00
Leonardo de Moura
04d3c6feeb fix: auto implicit behavior on constructors 2022-05-04 15:04:49 -07:00
Leonardo de Moura
a1af8074c9 feat: improve discriminant refinement procedure 2022-05-04 14:46:43 -07:00
Leonardo de Moura
16ed5a3213 fix: erase_irrelevant.cpp
It addresses issue reported at https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/'unreachable'.20code.20was.20reached.20by.20termination.20check/near/281159704
2022-05-04 08:06:59 -07:00
Leonardo de Moura
94b5a9b460 feat: improve split tactic 2022-05-03 17:46:50 -07:00
Gabriel Ebner
88e26b75b0 fix: actually abort with LEAN_ABORT_ON_PANIC
The previous null-pointer dereference was UB and therefore optimized
away.
2022-05-03 09:42:45 -07:00
Sebastian Ullrich
f6e74c677e doc: metaprogramming-arith: deduplicate 2022-05-03 18:38:36 +02:00
Sebastian Ullrich
87431da7b1 doc: metaprogramming-arith: style 2022-05-03 18:38:36 +02:00
Joscha
5749fb1474 fix: search for local refs only in current file
Fixed by adding the identifier's module as an argument to referringTo.
If the ident is RefIdent.const, this is ignored, but if it is
RefIdent.fvar, referringTo limits its search to the ident's module.
2022-05-03 16:53:03 +02:00
Sebastian Ullrich
e76a2a6d9e chore: normalize spelling 2022-05-03 10:26:11 +02:00
Leonardo de Moura
94abfdba6c feat: improve implementedBy errors, and relax type matching test 2022-05-02 08:48:15 -07:00
Leonardo de Moura
fe00dd8f29 fix: missing sanitizeNames at msgToInteractiveAux 2022-05-02 07:35:12 -07:00
Sebastian Ullrich
c755aa81bd fix: properly distinguish between internal and public linker flags 2022-05-02 13:53:52 +02:00
Sebastian Ullrich
2f3396e58a fix: non-termination in deduplication of lexical references 2022-05-02 09:51:14 +02:00
Sebastian Ullrich
09e4c00c68 fix: lexical references through x := e and similar macros 2022-05-01 17:46:05 +02:00
Leonardo de Moura
109363bc7e fix: closes #1132 2022-05-01 08:18:30 -07:00
Leonardo de Moura
4eb2cfec46 feat: make sure case' ... => tac does not use done after tac 2022-05-01 07:30:11 -07:00
Leonardo de Moura
03524305db fix: findTag?
If there is an exact match, return it.
2022-05-01 07:30:11 -07:00
Sebastian Ullrich
a0678b5f6f refactor: rename confusing Reference.isDeclaration field 2022-05-01 16:21:15 +02:00
Sebastian Ullrich
7512f8ab6e chore: CI: pin setup-msys2
https://github.com/msys2/setup-msys2/issues/216
2022-05-01 11:58:58 +02:00
Sebastian Ullrich
952abbf16b chore: remove obsolete workaround 2022-05-01 11:52:53 +02:00
Sebastian Ullrich
4174643dbd perf: optimize withAntiquot parenthesizer
Doesn't look like we'll get rid of the backtracking anytime soon
2022-05-01 11:52:53 +02:00
Leonardo de Moura
fa943d3864 chore: update RELEASES.md 2022-04-29 15:59:34 -07:00
Leonardo de Moura
ee0414b026 chore: update stage0 2022-04-29 15:51:47 -07:00
Leonardo de Moura
862492778a test: add deq_correct test from Zulip 2022-04-29 15:50:40 -07:00
Leonardo de Moura
cddf9ddd95 fix: forallAltTelescope heterogeneous equality support 2022-04-29 15:37:20 -07:00
Leonardo de Moura
c19672e99e fix: basic support for the new discriminant equality encoding at split
TODO: This is a temporary fix. We can do better.
2022-04-29 15:29:39 -07:00
Leonardo de Moura
c241ef61b1 fix: use HEq (if needed) for encoding h : discr equalities 2022-04-29 15:05:48 -07:00
Leonardo de Moura
351f0deae9 feat: add mkEqHEq 2022-04-29 14:31:36 -07:00
Leonardo de Moura
941ad84ece fix: getMkMatcherInputInContext 2022-04-29 12:44:36 -07:00
Leonardo de Moura
95ea0b92ea chore: fix test 2022-04-29 12:40:32 -07:00
Leonardo de Moura
d4d538cad8 fix: counterexample generation for new match encoding 2022-04-29 12:36:53 -07:00
Leonardo de Moura
ec932e389b chore: fix test 2022-04-29 12:30:45 -07:00
Leonardo de Moura
d3bc963e92 chore: update stage0 2022-04-29 12:20:46 -07:00
Leonardo de Moura
6e1c51dd1a feat: splitter proof for new match encoding 2022-04-29 12:19:24 -07:00
Leonardo de Moura
89441aac2a feat: match equation theorem generation for new h : discr notation encoding
TODO: splitter theorem generation still needs to be fixed.
2022-04-29 11:48:25 -07:00
Leonardo de Moura
24417ed466 feat: size, get, get!, getD, and getOp for Subarray 2022-04-29 09:55:45 -07:00
Leonardo de Moura
eac83586c6 chore: remove leftover 2022-04-29 09:10:27 -07:00
Leonardo de Moura
c959c80310 chore: reset local context at correct place 2022-04-29 09:08:44 -07:00
Leonardo de Moura
10d43492ba chore: fix test 2022-04-29 07:17:46 -07:00
Leonardo de Moura
8d9626dab7 feat: delaborate match h : d with ... 2022-04-29 07:17:46 -07:00
Leonardo de Moura
0f7754847d chore: style 2022-04-29 07:17:46 -07:00
Leonardo de Moura
d793d2f0fd feat: adapt elabMatchAltView to handle the new encoding for h : discr = pattern 2022-04-29 07:17:46 -07:00
Leonardo de Moura
7a369848a0 feat: new mkMatcher
TODO: adjust match elaborator
2022-04-29 07:17:46 -07:00
Leonardo de Moura
f4b4b14797 refactor: prepare to handle match h: notation at Meta\Match\Match.lean 2022-04-29 07:17:46 -07:00
Sebastian Ullrich
9b4feb3d13 perf: work around missed TCO 2022-04-29 16:16:09 +02:00
Sebastian Ullrich
b450fb8243 chore: CI: use stable Nix 2022-04-29 16:16:09 +02:00
Sebastian Ullrich
ff4a770c2d feat: annotate match tactic alternatives with expected state 2022-04-29 16:16:09 +02:00
Sebastian Ullrich
39a0de40dd feat: annotate <;> with expected state 2022-04-29 16:16:09 +02:00
Sebastian Ullrich
0a88f68d39 chore: finish with_annotate_state implementation 2022-04-29 16:16:09 +02:00
Sebastian Ullrich
d886a1da72 chore: update stage0 2022-04-29 16:16:09 +02:00
Sebastian Ullrich
db2a912112 feat: with_annotate_state helper tactic 2022-04-29 16:16:09 +02:00
Sebastian Ullrich
a167828b79 fix: refine previous commit's heuristic
Show indented state if there is no outer state that is leading & not indented
relative to the cursor position
2022-04-29 16:16:09 +02:00
Sebastian Ullrich
87b216a8e1 fix: do not show states from tactics indented further than the cursor 2022-04-29 16:16:09 +02:00
Sebastian Ullrich
cc5e7ee731 test: part of #1119 2022-04-29 16:16:09 +02:00
Sebastian Ullrich
b714a32d27 fix: revert "fix: show single final state after tactic combinator"
This reverts commit eb7bf2b272.
2022-04-29 16:16:09 +02:00
Sebastian Ullrich
78bf398830 fix: avoid signal-unsafe fprintf in stack overflow handler 2022-04-29 15:55:11 +02:00
Vincent de Haan
20e16f1c75 doc: add amssymb package to latex example to make it work in all cases 2022-04-28 11:21:12 +02:00
Leonardo de Moura
575b1187c5 feat: add Tactic.Context.recover for controlling error recovery
Moreover, when executing `tac_1 <|> tac_2`, we now disable error
recovery at `tac_1`.

closes #1126 #1127
2022-04-27 10:47:15 -07:00
Leonardo de Moura
ae913efa99 test: collect info view issues 2022-04-27 09:42:18 -07:00
Sebastian Ullrich
829c81d677 fix: skip antiquotations during parser recovery 2022-04-27 10:41:27 +02:00
Sebastian Ullrich
83f331b5e2 parseCommand: use do 2022-04-27 10:41:27 +02:00
Mario Carneiro
f37b700e6e fix: use correct number of none patterns for antiquotation splice 2022-04-27 09:55:27 +02:00
Leonardo de Moura
02d0a89229 chore: simpStar does not make sense for dsimp 2022-04-26 11:26:54 -07:00
Sebastian Ullrich
3d2215c93c doc: clean up syntax ToC 2022-04-26 18:58:45 +02:00
Leonardo de Moura
cae59c6916 chore: remove staging workarounds 2022-04-26 08:23:43 -07:00
Leonardo de Moura
25053594ff chore: update stage0 2022-04-26 08:22:25 -07:00
Leonardo de Moura
6af1da450e feat: disable only eta for classes during TC resolution
closes #1123
2022-04-26 08:20:39 -07:00
Sebastian Ullrich
814f614369 fix: simp attributes and macro scopes 2022-04-26 10:39:02 +02:00
Leonardo de Moura
3cf642688b fix: do not generate equation theorems while processing dsimp arguments 2022-04-25 18:11:32 -07:00
Leonardo de Moura
6bc5433b17 fix: add support for heterogeneous equality at processGenDiseq 2022-04-25 16:56:03 -07:00
Leonardo de Moura
4a4473ff90 chore: update stage0 2022-04-25 16:35:47 -07:00
Leonardo de Moura
40c8db7494 feat: improve argument type mismatch error position, and do not stop at application type mismatch errors 2022-04-25 16:30:40 -07:00
Leonardo de Moura
0c8a6d8977 feat: exists es:term,+ tactic
cc: @fgdorais
2022-04-25 15:35:31 -07:00
Leonardo de Moura
29b340aa36 fix: consume Expr.mdata at congr tactic
fixes #1118
2022-04-25 06:33:32 -07:00
Leonardo de Moura
3ad8dcb7ff fix: nasty interaction between TC resolution and Eta for structures
See
https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/.60constructor.60.20and.20.60Applicative.60/near/279984801
2022-04-24 08:19:29 -07:00
Leonardo de Moura
47b379e1bc feat: dsimp! tactic 2022-04-23 18:41:04 -07:00
Leonardo de Moura
342a26a023 feat: dsimp tactic 2022-04-23 18:05:18 -07:00
Leonardo de Moura
13bcbe91cd fix: regression reported at issue #1113
see issue #1113
2022-04-23 15:39:04 -07:00
Leonardo de Moura
4ab57475a0 chore: simplify proofs 2022-04-23 12:47:10 -07:00
Leonardo de Moura
e25a116821 chore: RELEASES.md 2022-04-23 12:16:36 -07:00
Leonardo de Moura
ed12b62e28 fix: InfoTree was missing information for (pseudo) match patterns such as x + 1.
This kind of pattern has to be reduced to a constructor, and the
`PatternWithRef` information was being lost in the process.
2022-04-23 12:08:59 -07:00
Leonardo de Moura
305d8e641c chore: style 2022-04-23 10:47:53 -07:00
Sebastian Ullrich
eb7bf2b272 fix: show single final state after tactic combinator 2022-04-23 17:42:32 +02:00
Sebastian Ullrich
240c5e15e9 fix: show final goal state at end of tactic combinator 2022-04-23 17:15:32 +02:00
Leonardo de Moura
34c75fc443 feat: allow even if the expected type is not available
see issue #1116
2022-04-23 08:00:27 -07:00
Leonardo de Moura
36fad4bba0 fix: do not assign metavariables in the major premise type when trying K 2022-04-23 07:31:51 -07:00
Leonardo de Moura
a82abee1b2 feat: sum of monomials normal form by reflection 2022-04-22 18:51:48 -07:00
Leonardo de Moura
875bf9bf34 fix: apply dsimp at lambda binders
This fixes another regression reported at #1113
2022-04-22 13:10:21 -07:00
Leonardo de Moura
c13ed7c0de fix: regression reported at #1113
See #1113
2022-04-22 11:43:58 -07:00
Leonardo de Moura
864c4c5030 chore: update stage0 2022-04-22 09:53:47 -07:00
Leonardo de Moura
2a2aeec085 feat: LSP semantic token for where and let rec declarations 2022-04-22 09:52:20 -07:00
Sebastian Ullrich
ca3f1a84b0 doc: fix example style 2022-04-22 16:26:16 +02:00
Leonardo de Moura
a5bf0d5ea5 chore: invert setup chapters by making the quickstart the default and the other one "extended setup notes" 2022-04-21 18:09:54 -07:00
Leonardo de Moura
66c82dadc9 fix: the default value for structure fields may now depend on the structure parameters 2022-04-21 17:38:19 -07:00
Leonardo de Moura
09dfd97593 chore: remove temporary workaround 2022-04-21 16:29:08 -07:00
Leonardo de Moura
46dbddabd5 chore: update stage0 2022-04-21 16:27:00 -07:00
Leonardo de Moura
d1f10a2e71 feat: apply rfl theorems at dsimp
closes #1113
2022-04-21 16:26:57 -07:00
Leonardo de Moura
2a0dc1804b feat: improve isRflProof and isRflTheorem
The `Eq.symm` of a `rfl` theorem is a `rfl` theorem, the application
of `rfl` theorem too.
2022-04-21 15:40:38 -07:00
Leonardo de Moura
57c3114875 fix: simpAll and tests
We need another `update stage0` to remove workaround at `AC.lean`
2022-04-21 15:00:07 -07:00
Leonardo de Moura
da33347e9d fix: use defauld reducibility setting at mkImpDepCongrCtx and mkImpCongrCtx 2022-04-21 14:55:29 -07:00
Leonardo de Moura
abc75053b6 chore: update stage0 2022-04-21 13:43:36 -07:00
Leonardo de Moura
f891c5724d feat: track rfl simp theorems
See issue #1113

We need update stage0 before closing the issue.
2022-04-21 13:42:04 -07:00
Leonardo de Moura
0b92195ec8 feat: refine auto bound implicit feature 2022-04-21 10:17:15 -07:00
Leonardo de Moura
d81c124479 chore: update stage0 2022-04-21 08:37:31 -07:00
Leonardo de Moura
4727fd6883 feat: do not hightlight auxiliary declarations used to compile recursive definitions as variables
They are "morally" constants.
2022-04-21 08:11:22 -07:00
Leonardo de Moura
d8ad343885 test: add Expr.eq_of_toPoly_eq 2022-04-20 23:04:29 -07:00
Leonardo de Moura
6bdeb6c9cb test: add support for sub as som.lean 2022-04-20 22:59:55 -07:00
Leonardo de Moura
6e09dfae1e test: simplify sum of monomials 2022-04-20 22:31:52 -07:00
Leonardo de Moura
14bfe57ba8 test: sum of monomials by reflection 2022-04-20 19:19:50 -07:00
Leonardo de Moura
2a36ae4627 feat: add List.le_antisymm 2022-04-20 16:31:25 -07:00
Leonardo de Moura
9852fe3db8 feat: add simp theorems 2022-04-20 16:14:01 -07:00
Leonardo de Moura
bb3fc358c9 feat: add LawfulBEq Int instance 2022-04-20 14:52:41 -07:00
Leonardo de Moura
73076b855c fix: bug at processGenDiseq 2022-04-20 10:46:05 -07:00
Leonardo de Moura
4a18679c92 chore: include problematic match auxiliary declaration name in the error message 2022-04-20 10:46:05 -07:00
Sebastian Ullrich
e1fbfb677e doc: missing file 2022-04-20 19:13:53 +02:00
Sebastian Ullrich
84cc167f95 doc: fix example code & style 2022-04-20 19:05:43 +02:00
Sebastian Ullrich
c354a9f62f doc: link orphan syntax tutorial 2022-04-20 18:49:38 +02:00
Sebastian Ullrich
5f6bbe59ef doc: fold sub-chapters by default 2022-04-20 18:46:30 +02:00
Sebastian Ullrich
b6446902c2 feat: server.stderrAsMessages option
/cc @leodemoura
2022-04-19 22:29:26 +02:00
Leonardo de Moura
597313135a fix: index out of bounds at computeFixedIndexBitMask
closes #1112
2022-04-19 05:21:43 -07:00
Leonardo de Moura
d0ccb73fc9 chore: update stage0 2022-04-19 05:11:19 -07:00
Leonardo de Moura
556ace5cc1 chore: update RELEASES.md 2022-04-18 17:03:01 -07:00
Leonardo de Moura
4848ad4869 feat: implement autoUnfold at simp
Right now, it only supports the following kind of definitions
- Recursive definitions that support smart unfolding.
- Non-recursive definitions where the body is a match-expression. This
kind of definition is only unfolded if the match can be reduced.
2022-04-18 16:51:52 -07:00
Leonardo de Moura
f87066a0a5 chore: update stage0 2022-04-18 16:01:22 -07:00
Leonardo de Moura
18832ad91c feat: add autoUnfold to Simp.Config
Add macros for conveniently setting `arith` and `autoUnfold`.
2022-04-18 15:59:30 -07:00
Leonardo de Moura
470d0077ca chore: update stage0 2022-04-18 14:57:02 -07:00
Leonardo de Moura
bb2df569bc fix: bug at declare_config_elab 2022-04-18 14:56:22 -07:00
Leonardo de Moura
e69e469a37 chore: update test 2022-04-18 11:56:46 -07:00
Leonardo de Moura
e6aee1e463 feat: make sure cases and induction alternatives are processed using the order provided by the user
Motivation: improve the effectiveness of the `save` and `checkpoint` tactics.
2022-04-18 11:45:36 -07:00
Leonardo de Moura
822375aaff chore: ensure _ alternative is the last one in the cases and induction tactics 2022-04-18 11:18:03 -07:00
Leonardo de Moura
5599cefe2e feat: add sleep tactic for debugging purposes 2022-04-18 09:53:45 -07:00
Leonardo de Moura
d9f007e4dd fix: tactic cache corruption 2022-04-17 15:52:21 -07:00
Leonardo de Moura
607a590238 test: pge example 2022-04-17 15:17:28 -07:00
Leonardo de Moura
40129203b2 chore: update RELEASES.md 2022-04-17 13:55:46 -07:00
Leonardo de Moura
d4183cf646 feat: add option tactic.dbg_cache 2022-04-17 13:47:28 -07:00
Leonardo de Moura
4a303ec214 feat: include tactic position in the cache key 2022-04-17 13:47:12 -07:00
Leonardo de Moura
deab1ebc56 feat: add save tactic
It is a more convenient way of creating checkpoints.
2022-04-17 08:46:08 -07:00
Leonardo de Moura
fa16a96692 chore: avoid nested noImplicitLambda annotations 2022-04-17 08:09:10 -07:00
Leonardo de Moura
726b735c6d fix: using invalid name generator at ContextInfo.runMetaM
Already used `MVarId`s were being "reused" potentially creating cyclic
metavar assignment. See issue #1031 for an example.

closes #1031
2022-04-15 18:42:34 -07:00
Leonardo de Moura
7fc139fdb0 chore: add doc-string for tactics 2022-04-15 14:19:03 -07:00
Leonardo de Moura
d4f514b964 chore: update stage0 2022-04-15 13:49:51 -07:00
Leonardo de Moura
7995cb071f chore: add assertions to make sure TagDeclarationExtension and MapDeclarationExtension are not being misused
see #1111
2022-04-15 13:49:35 -07:00
Sebastian Ullrich
7797fa3e2d fix: fun (x ...) ... should not be treated as a pattern 2022-04-15 10:00:26 -07:00
Leonardo de Moura
bc7f4fd02b test: hasCSimpAttribute 2022-04-15 09:55:10 -07:00
Leonardo de Moura
33a7f75599 chore: update stage0 2022-04-15 09:46:23 -07:00
Leonardo de Moura
a57403be6e feat: add hasCSimpAttribute 2022-04-15 09:44:50 -07:00
Ed Ayers
d8e2d58da7 doc: InfoTree code review
Co-authored-by: Wojciech Nawrocki <wjnawrocki+gh@protonmail.com>
2022-04-15 09:07:35 -07:00
E.W.Ayers
7d128c17dc doc: #1107 review 2022-04-15 09:04:28 -07:00
E.W.Ayers
9598e39c82 doc: InfoTree docstrings 2022-04-15 09:04:26 -07:00
Sebastian Ullrich
458da0e27b chore: update LeanInk 2022-04-15 08:53:34 -07:00
E.W.Ayers
06e8cf5200 fix: allow non-leaf custom info
At the moment InfoTree has a constructor ofJson but this means that
you can't have a non-leaf ofJson. It would be better to have `ofJson` be a constructor of `Info`.
This is what this PR does.
2022-04-15 08:53:34 -07:00
Leonardo de Moura
4aee759ded fix: make sure rfl is an extensible tactic
closes #1109
2022-04-15 08:51:05 -07:00
Sebastian Ullrich
f98b6a3bb1 fix: fall-out from syntax kind lookup change 2022-04-15 08:50:46 -07:00
Sebastian Ullrich
a2baf2cb96 refactor: split term/command quotations 2022-04-15 08:50:46 -07:00
Sebastian Ullrich
ca8fdcaa0c chore: update stage0 2022-04-15 08:50:46 -07:00
Sebastian Ullrich
e1fbc04c3b chore: accept unregistered syntax kinds in stage 1 2022-04-15 08:50:46 -07:00
E.W.Ayers
712967c6f6 refactor: registerRpcProcedure 2022-04-13 13:23:04 -07:00
Wojciech Nawrocki
d649fc9159 fix: RPC error message 2022-04-13 13:23:04 -07:00
Wojciech Nawrocki
367b0fc80f doc: note persistent exts are sometimes needed 2022-04-13 13:23:04 -07:00
E.W.Ayers
30dfabb2c7 fix: userRpcProcedures uses a persistent env ext 2022-04-13 13:23:04 -07:00
Leonardo de Moura
081dff288f fix: debug build 2022-04-13 13:12:53 -07:00
Leonardo de Moura
f875c2d107 chore: update release notes 2022-04-13 10:33:25 -07:00
Leonardo de Moura
bcb9c2c2a3 chore: fix test 2022-04-13 10:27:59 -07:00
Leonardo de Moura
f2c3685e83 chore: update stage0 2022-04-13 10:20:41 -07:00
Leonardo de Moura
8d2d0b3fbe chore: remove {} from structure command 2022-04-13 10:19:00 -07:00
Leonardo de Moura
efb859013e chore: ignore {} annotations at mk_projections 2022-04-13 10:16:41 -07:00
Leonardo de Moura
e00550c57e chore: remove {} occurrences 2022-04-13 10:14:51 -07:00
Leonardo de Moura
3d9439f3c9 chore: missing annotation 2022-04-13 09:03:58 -07:00
Leonardo de Moura
9126d33dda doc: update release notes 2022-04-13 09:01:55 -07:00
Leonardo de Moura
b267a4b288 chore: update stage0 2022-04-13 08:49:15 -07:00
Leonardo de Moura
bd35e8a2be chore: remove {} from ctor parser 2022-04-13 08:47:21 -07:00
Leonardo de Moura
3e0a975e9c chore: fix test 2022-04-13 08:37:34 -07:00
Leonardo de Moura
1f4039a25d chore: remove {} from Eq.refl and HEq.refl 2022-04-13 08:35:02 -07:00
Leonardo de Moura
18868cbaba chore: update stage0 2022-04-13 08:33:14 -07:00
Leonardo de Moura
f098b1c291 test: for regression from last year's course at KIT 2022-04-13 08:31:43 -07:00
Leonardo de Moura
dbf5366704 feat: ignore {} annotation at constructors 2022-04-13 08:30:21 -07:00
Leonardo de Moura
2ec8385767 fix: isDomainDefEq 2022-04-13 07:54:47 -07:00
Leonardo de Moura
600769811e fix: bug at fixedIndicesToParams 2022-04-13 07:33:32 -07:00
Leonardo de Moura
3bdb385c19 fix: make sure "eta for structures" in the elaborator uses projection functions if available 2022-04-11 19:23:10 -07:00
Leonardo de Moura
1add9b814b chore: style 2022-04-11 18:48:09 -07:00
Leonardo de Moura
3de607193f fix: withoutModifyingStateWithInfoAndMessagesImpl
Make sure it does not produced a corrupted `InfoTree`.
2022-04-11 16:57:55 -07:00
Leonardo de Moura
9f8dd99ccd fix: macro declare_config_elab was corrupting the info tree 2022-04-11 16:49:56 -07:00
Leonardo de Moura
e49179c807 fix: simp at local declaration should not create an auxiliary declaration when result is definitionally equal 2022-04-11 07:54:15 -07:00
Leonardo de Moura
fb64a4ccc0 fix: unfold should not create an auxiliary declaration when result is definitionally equal
This commit fixes an issue reported on Zulip
https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/Unfolding.20the.20type.20of.20a.20variable.20creates.20a.20new.20variable
2022-04-11 07:54:15 -07:00
larsk21
7cf4642d1b fix: apply workspace symbol limit after sorting by score 2022-04-11 16:08:55 +02:00
larsk21
235b6d8f69 fix: remove unnecessary fuzzy scoring rule 2022-04-11 16:08:55 +02:00
Jannis Limperg
5ff8f64255 feat: add IO.monoNanosNow 2022-04-11 12:16:20 +02:00
Jannis Limperg
6459ccc43c fix: prevent overflow in lean_io_mono_ms_now 2022-04-11 12:16:20 +02:00
Leonardo de Moura
c2c2783f32 feat: improve dot name resolution by lazily unfolding resulting type
See new test to understand issue being fixed by this commit.
2022-04-10 14:37:27 -07:00
Leonardo de Moura
ed85a68550 chore: missing backtick 2022-04-10 11:11:51 -07:00
Leonardo de Moura
e4304ea1de fix: always save completion info at resolveName
See new test.
2022-04-10 08:00:03 -07:00
Leonardo de Moura
348037abbf chore: move states35 to bench directory
@Kha It breaks in the CI in debug mode (stack overflow).
I think we have a mechanism for skipping some tests in debug mode, but
I forgot how it works.
2022-04-09 15:46:28 -07:00
Leonardo de Moura
8b53cc8dbb chore: update RELEASES.md 2022-04-09 15:39:40 -07:00
Leonardo de Moura
4d077214f9 feat: jump to definition for match pattern variables 2022-04-09 15:36:42 -07:00
Leonardo de Moura
1db11ed5c7 test: native_decide with 35 states 2022-04-09 14:48:53 -07:00
Leonardo de Moura
86bd70ac62 test: native_decide 2022-04-09 14:41:22 -07:00
Marcus Rossel
a8db183d5c chore: typos 2022-04-09 13:02:01 -07:00
Leonardo de Moura
027fec76da chore: update stage0 2022-04-09 12:25:43 -07:00
Leonardo de Moura
4374ec4ad8 perf: use Kernel isDefEq for ground terms
`state8.lean` now takes 0.29s. It was 0.37s.
2022-04-09 12:24:20 -07:00
Leonardo de Moura
e3dcce5320 chore: remove temporary workarounds 2022-04-09 12:13:37 -07:00
Leonardo de Moura
948c3c0ec4 chore: update stage0 2022-04-09 12:12:17 -07:00
Leonardo de Moura
4dd2b26e06 fix: rfl error message and corner case
The new `rfl` slightly improves the performance for `rfl` proofs of
ground terms.
Example: `state8.lean` now takes 0.37s. It was 0.52s.
2022-04-09 12:08:04 -07:00
Leonardo de Moura
628e33bf8a feat: activate new rfl tactic implementation 2022-04-09 12:01:56 -07:00
Leonardo de Moura
47e7e03f79 chore: update stage0 2022-04-09 11:58:12 -07:00
Leonardo de Moura
03f6b87647 feat: add hand-written rfl tactic
It requires update stage0
2022-04-09 11:57:27 -07:00
Leonardo de Moura
298281baaf perf: skip logUnassignedUsingErrorInfos if pendingMVarIds is empty
`state8.lean` now takes 0.52s. It was 0.76s.
2022-04-09 10:45:52 -07:00
Leonardo de Moura
7d99f6f555 perf: isClassQuick? was incorrectly producing undef
Then `isClassExpensive?` was being invoked too often. In some
benchmarks the performance hit was substantial. For example,
in the new test `state8.lean`. The runtime on my machine went from 2s
to 0.76s.
2022-04-09 10:38:49 -07:00
Leonardo de Moura
6e02514eee chore: style 2022-04-09 10:27:31 -07:00
Leonardo de Moura
417421dbae fix: auto completion when autoBoundImplicit is active 2022-04-09 09:11:45 -07:00
Leonardo de Moura
87e6581e6b fix: constructor elaboration
fixes #1098
2022-04-08 18:19:06 -07:00
Leonardo de Moura
1c236a0d43 chore: update stage0 2022-04-08 15:05:38 -07:00
Leonardo de Moura
3cf425ba52 fix: pattern hover information
We annotate patterns with the corresponding `Syntax` during
elaboration, and do not populate the info tree. Reason: the set of
pattern variables is not known during pattern elaboration.
2022-04-08 15:03:42 -07:00
Leonardo de Moura
4793c7e734 feat: add isAppOfArity variant that skips Expr.mdata 2022-04-08 15:01:57 -07:00
Leonardo de Moura
152eff5cea chore: missing double ticks 2022-04-08 15:01:57 -07:00
Leonardo de Moura
ea682830d1 refactor: change addTermInfo type 2022-04-08 15:01:57 -07:00
Sebastian Ullrich
74435013f4 chore: remove now-broken workarounds 2022-04-08 15:53:58 +02:00
Sebastian Ullrich
51d6a75a0f chore: update stage0 2022-04-08 15:53:58 +02:00
Sebastian Ullrich
4aed79a13e feat: less strict, hopefully more helpful syntax ident matching semantics 2022-04-08 15:53:58 +02:00
Leonardo de Moura
5d8b4f33c0 feat: improve binder names introduced by the match discriminant refinement feature 2022-04-08 06:49:09 -07:00
Leonardo de Moura
099fba43d3 chore: remove trace[Meta.debug] leftovers 2022-04-08 06:49:09 -07:00
E.W.Ayers
917fa74366 doc: docstrings for decls and attributes
Co-authored-by: Sebastian Ullrich <sebasti@nullri.ch>
2022-04-08 04:19:38 -07:00
Leonardo de Moura
cec0f81926 chore: add instantiateMVars 2022-04-07 18:46:45 -07:00
Leonardo de Moura
37b321229f feat: make sure hover information does not include @ for constants 2022-04-07 18:40:04 -07:00
Leonardo de Moura
55989c25fc chore: remove unnecessary args 2022-04-07 18:19:15 -07:00
Leonardo de Moura
de2e2447d2 chore: style 2022-04-07 17:35:05 -07:00
Leonardo de Moura
dcb88d969a feat: improve auto implicit binder names in definitions/theorems 2022-04-07 14:46:59 -07:00
Leonardo de Moura
cd0d7e676f chore: rename renameMVar => setMVarUserName 2022-04-07 13:50:58 -07:00
Leonardo de Moura
00c4524e80 chore: register Elab.induction trace class 2022-04-07 13:22:40 -07:00
Leonardo de Moura
c26e968c24 chore: style 2022-04-07 11:25:45 -07:00
Leonardo de Moura
fa9b0f6c7e feat: remove space before propositions with inaccessible names 2022-04-07 07:54:50 -07:00
Leonardo de Moura
9de6961906 chore: to doc string 2022-04-07 07:29:23 -07:00
Leonardo de Moura
27cd678717 doc: improve contradiction doc string 2022-04-06 19:27:23 -07:00
Leonardo de Moura
e5b8d94a65 chore: remove unnecessary annotation 2022-04-06 16:38:16 -07:00
Leonardo de Moura
5b15a97d72 chore: break long lines 2022-04-06 16:37:38 -07:00
Leonardo de Moura
39093188bf chore: use cdot 2022-04-06 16:32:20 -07:00
Leonardo de Moura
911ed750ff doc: document 2022-04-06 16:30:02 -07:00
Leonardo de Moura
005f964749 feat: save info at renameInaccessibles
We now have info variables introduced by the `next` and `case` tactics
2022-04-06 16:16:20 -07:00
Leonardo de Moura
317492d207 test: add test for Lean 3 refine bug reported on Zulip
https://leanprover.zulipchat.com/#narrow/stream/113488-general/topic/.60refine.60.20bug.20.3F/near/278031110
2022-04-06 16:04:17 -07:00
Leonardo de Moura
847f5b21a6 feat: save info for cases and induction alt vars 2022-04-06 15:53:58 -07:00
Leonardo de Moura
cd82a24ca9 chore: avoid "denote" overloading
It the overload does not affect elaboration, but pollutes the info view.
2022-04-06 15:00:13 -07:00
Leonardo de Moura
36e032cf94 chore: fix test 2022-04-06 14:55:27 -07:00
Leonardo de Moura
0bfcf434ac fix: jump to definition inside of a mutually inductive declaration 2022-04-06 14:43:30 -07:00
Leonardo de Moura
1107705525 fix: jump to definition inside recursive definitions was not working on VS Code
Remark: it was working on Emacs.
2022-04-06 14:27:49 -07:00
Leonardo de Moura
574927ab0d fix: jump to definition for recursive declarations 2022-04-06 13:01:16 -07:00
Leonardo de Moura
d380808930 fix: generalize if target is a let-declaration 2022-04-06 11:08:41 -07:00
Sebastian Ullrich
6841f37662 chore: update stage0 2022-04-06 19:43:07 +02:00
Sebastian Ullrich
24697026e8 feat: always accept antiquotations, simplify quotDepth code 2022-04-06 19:43:07 +02:00
Sebastian Ullrich
8f2f6bc17d doc: adjust alectryon.css a little 2022-04-06 09:06:49 -07:00
Sebastian Ullrich
020fb82888 doc: clean up examples markup 2022-04-06 09:06:49 -07:00
Sebastian Ullrich
2aaac3f94b doc: embed examples into doc book 2022-04-06 09:06:49 -07:00
Sebastian Ullrich
e10e664cc1 chore: typos 2022-04-06 10:21:53 +02:00
Sebastian Ullrich
3cf2afa42e refactor: clean up parsers using withAnonymousAntiquot := false 2022-04-06 10:21:53 +02:00
Sebastian Ullrich
dfd469743c chore: update stage0 2022-04-06 10:21:53 +02:00
Sebastian Ullrich
ffee6676ef feat: allow adjusting anonymous antiquot generation at leading_parser 2022-04-06 10:21:53 +02:00
Sebastian Ullrich
99464c352e chore: remove restriction on leading/trailing_parser macros
I don't think we quote any parsers right now
2022-04-06 10:21:53 +02:00
Sebastian Ullrich
7460878e05 chore: define WIN32_LEAN_AND_MEAN 2022-04-06 09:38:19 +02:00
Leonardo de Moura
149cd1ee82 chore: fix test 2022-04-05 21:04:55 -07:00
Leonardo de Moura
058aea8922 fix: withSaveInfoContext at Inductive.lean
It was in the context of `withInductiveLocalDecls`. This introduced
unnecessary `_root_` in the info view and hover information.

For example, when hovering over
```lean
inductive Ty where
  | int
  | bool
  | fn (a r : Ty)
```
We would get `Ty.int : _root_.Ty` when hovering over the `int`.
2022-04-05 20:58:06 -07:00
Leonardo de Moura
f5583d7771 chore: update stage0 2022-04-05 20:52:30 -07:00
Leonardo de Moura
7c5575631a feat: remove _tmp_ind_univ_param elaboration hack
The new approach produces better type information in the "info view" when
hovering over inductive declarations.
2022-04-05 20:51:15 -07:00
Leonardo de Moura
27e07d1b25 fix: remove auxiliary discriminants before elaborating patterns 2022-04-05 19:37:56 -07:00
Leonardo de Moura
d65691626c chore: update stage0 2022-04-05 17:38:43 -07:00
Leonardo de Moura
eae4b92b0d feat: use sorry if failed to synthesize default element for unsafe constant 2022-04-05 16:52:54 -07:00
Sebastian Ullrich
d2c626e158 doc: refine development manual 2022-04-05 16:03:24 +02:00
Leonardo de Moura
18707692a8 doc: add doc strings to some tactics 2022-04-05 06:27:09 -07:00
Leonardo de Moura
16523647b8 doc: add doc strings to some tactics 2022-04-05 06:27:09 -07:00
Sebastian Ullrich
adcdd16d7a doc: include missing chapter 2022-04-04 17:56:19 +02:00
Leonardo de Moura
6aee3fb304 chore: fix broken links 2022-04-03 10:32:00 -07:00
Leonardo de Moura
5470100830 feat: better binder names at reorderCtorArgs 2022-04-03 10:03:47 -07:00
Leonardo de Moura
a8ee6029c2 chore: remove workaround from example 2022-04-03 09:25:47 -07:00
Leonardo de Moura
61ae72330f feat: improve universe level contraint checks in inductive datatype constructors 2022-04-03 09:19:22 -07:00
Leonardo de Moura
3ee8ceafb4 feat: better error message when constructor parameter universe level is too big 2022-04-03 08:37:38 -07:00
Leonardo de Moura
ef8fecff79 feat: add Level.geq 2022-04-03 08:18:14 -07:00
Leonardo de Moura
310961cc35 chore: add scaffolding for checking ctor universe params 2022-04-03 07:33:02 -07:00
Leonardo de Moura
743f6dd3a2 chore: cleanup 2022-04-03 06:56:27 -07:00
Leonardo de Moura
ca9b494e4d chore: use specialize tactic 2022-04-02 19:35:36 -07:00
Leonardo de Moura
d7abecd07d test: addDecorations without partial 2022-04-02 19:08:21 -07:00
Leonardo de Moura
c873ad6ef3 test: recursive function on Syntax without partial 2022-04-02 18:43:45 -07:00
Leonardo de Moura
9d55d7bf9e feat: add helper tactic for applying List.sizeOf_lt_of_mem in termination proofs 2022-04-02 18:38:55 -07:00
Leonardo de Moura
64cfbc1ae3 feat: add helper tactic for applying sizeOf (a.get i) < sizeOf a automatically in termination proofs 2022-04-02 18:29:41 -07:00
Leonardo de Moura
562af50191 feat: add ForIn' instance for Range 2022-04-02 18:22:21 -07:00
Leonardo de Moura
2c7c7471db feat: add case' tactic for writing macros
It is similar to `case` but does not admit goal in case of failure.
This is useful for writing macros.
2022-04-02 17:54:06 -07:00
Leonardo de Moura
443dd79a02 feat: sizeOf theorems for Lean.Name 2022-04-02 17:09:55 -07:00
Leonardo de Moura
03ec8cb30b feat: missing sizeOf theorems for Array.get and List.get 2022-04-02 16:04:46 -07:00
Leonardo de Moura
9f29d7ecb7 feat: add stop tactic macro 2022-04-02 15:39:03 -07:00
Leonardo de Moura
3d4e6282b7 chore: fix link to examples 2022-04-02 15:29:12 -07:00
Leonardo de Moura
78007be772 test: for Lean 3 hover issue reported on Zulip 2022-04-02 15:21:24 -07:00
Leonardo de Moura
4fa5f50559 feat: implement TODO at "fixed indices to parameters"
The missing feature (TODO in the code) is needed for the `BinTree` example.
2022-04-02 14:37:24 -07:00
Leonardo de Moura
9fe5458077 feat: do not display inaccessible proposition names if they do not have forward dependencies
Even if `pp.inaccessibleNames = true`
2022-04-02 13:15:17 -07:00
Leonardo de Moura
95bd55bc21 chore: fix typo and remove unnecessary discriminant 2022-04-02 13:15:17 -07:00
Sebastian Ullrich
4fcc7c78dd chore: update LeanInk 2022-04-02 18:13:42 +02:00
Leonardo de Moura
d65ceafc99 chore: break long lines 2022-04-02 07:54:40 -07:00
Leonardo de Moura
9ee3cb642a chore: formatting 2022-04-02 07:53:20 -07:00
Leonardo de Moura
e4fb9c8f47 chore: break long lines 2022-04-02 07:50:27 -07:00
Leonardo de Moura
375692cb92 doc: explain attribute [local simp] 2022-04-02 07:46:32 -07:00
Leonardo de Moura
16649beb19 doc: explain details 2022-04-02 07:39:07 -07:00
Leonardo de Moura
dee5dbca98 chore: cleanup example 2022-04-02 07:13:46 -07:00
Leonardo de Moura
7f00352d33 chore: backtick issue in documentation 2022-04-02 06:55:23 -07:00
Leonardo de Moura
e058fe65a9 feat: make the hypothesis name optional in the by_cases tactic 2022-04-01 19:36:13 -07:00
Leonardo de Moura
ed935ed7a7 doc: binary search trees 2022-04-01 19:30:28 -07:00
Leonardo de Moura
8636594dac chore: add [simp] to Nat.lt_irrefl 2022-04-01 18:50:32 -07:00
Leonardo de Moura
be014b1fc9 fix: dotted notation corner case 2022-04-01 18:20:44 -07:00
Leonardo de Moura
cfb4e306f7 refactor: replace length_dropLast theorem 2022-04-01 16:44:24 -07:00
Leonardo de Moura
2ec40e91da chore: update stage0 2022-04-01 15:48:09 -07:00
Leonardo de Moura
a926cd1698 fix: mkUnfoldProof
The hypotheses in an equation theorem may depend on each other
2022-04-01 15:47:24 -07:00
Leonardo de Moura
4a0f68de83 fix: split tactic issue 2022-04-01 15:47:24 -07:00
Leonardo de Moura
ea8f31144e feat: add predicate to generalize tactic to select subterms to be generalized 2022-04-01 15:47:24 -07:00
Sebastian Ullrich
524dc5d47c chore: Nix: update Nixpkgs 2022-04-02 00:08:24 +02:00
Leonardo de Moura
d473cc5a4c chore: update release notes for issue #1090
closes #1090
2022-04-01 11:38:50 -07:00
Leonardo de Moura
0241d7c197 chore: fix tests 2022-04-01 11:34:50 -07:00
Leonardo de Moura
f45712ce74 chore: update stage0 2022-04-01 11:29:09 -07:00
Leonardo de Moura
fdd1cb5751 chore: remove workarounds for #1090 2022-04-01 11:28:17 -07:00
Leonardo de Moura
48a3668780 chore: fix repo 2022-04-01 11:24:30 -07:00
Leonardo de Moura
16b2237d2d chore: update stage0 2022-04-01 11:24:22 -07:00
Leonardo de Moura
799c701f56 fix: inconsistency between syntax and kind names
TODO: remove staging workarounds

see #1090
2022-04-01 11:20:16 -07:00
Leonardo de Moura
b6cc3c959b chore: update stage0 2022-04-01 11:14:47 -07:00
Leonardo de Moura
68acfc7fb9 chore: prepare for #1090 2022-04-01 11:11:28 -07:00
Leonardo de Moura
8dddb0ddc7 chore: update stage0 2022-04-01 09:37:52 -07:00
Leonardo de Moura
09de67780f chore: prepare for #1090 2022-04-01 09:35:06 -07:00
Leonardo de Moura
414f5596a6 test: Nat.binrec example 2022-04-01 08:29:44 -07:00
Leonardo de Moura
d1022e5587 chore: add Nat.div_add_mod 2022-04-01 08:20:00 -07:00
Leonardo de Moura
92382ea47b fix: checkpoint 2022-04-01 05:53:18 -07:00
E.W.Ayers
9fdb7429d4 doc: edits to MonadControl 2022-04-01 10:06:58 +02:00
E.W.Ayers
4c2fedae50 doc: fix @Kha's issues with MonadControl 2022-04-01 10:06:58 +02:00
Leonardo de Moura
4c9c62752e feat: improve checkpoint tactic 2022-03-31 20:51:53 -07:00
Leonardo de Moura
23f41fddb3 feat: basic tactic cache
TODO: move `IO.Ref` to command
2022-03-31 19:53:03 -07:00
Leonardo de Moura
059459b097 fix: occurs check at refine tactic 2022-03-31 18:08:05 -07:00
Leonardo de Moura
87db7a9115 chore: style 2022-03-31 17:33:56 -07:00
Leonardo de Moura
096e4eb6d0 fix: equation generation for nested recursive definitions
The issue was raised on Zulip. The issue is triggered in
declarations containing overlapping patterns and nested recursive
definitions occurring as the discriminant of `match`-expressions.
Recall that Lean 4 generates conditional equations for declarations
containing overlapping patterns.
To address the issue we had to "fold" `WellFounded.fix` applications
back as recursive applications of the functions being defined.

The new test exposes the issue.
2022-03-31 17:04:06 -07:00
Leonardo de Moura
6652d2665d chore: remove old comment 2022-03-31 15:59:31 -07:00
Leonardo de Moura
0ce967ad90 chore: update stage0 2022-03-31 14:53:37 -07:00
Leonardo de Moura
d21e62ecb7 refactor: custom simpMatch for WF module
It is just the skeleton right now.
2022-03-31 14:51:07 -07:00
Leonardo de Moura
1ab57d4fd4 feat: store fixedPrefixSize at WF.EqnInfo 2022-03-31 14:47:52 -07:00
Leonardo de Moura
734902bd3c test: add split list example from Zulip without sorrys 2022-03-31 13:03:58 -07:00
Leonardo de Moura
23f3de5061 chore: proper trace message class 2022-03-31 11:04:42 -07:00
Leonardo de Moura
2bd04285f8 fix: #1087
This commit is using the easy fix described at issue #1087.
Hopefully the performance overhead is small.

closes #1087
2022-03-30 18:48:02 -07:00
Leonardo de Moura
63b9060ce9 chore: fix comments 2022-03-30 16:23:06 -07:00
Leonardo de Moura
3dd0c84c4d chore: enforce naming convetion for tactics 2022-03-30 16:19:05 -07:00
Leonardo de Moura
df063a47fa chore: fix link 2022-03-30 13:44:22 -07:00
Leonardo de Moura
a509b0c615 test: Sign 2022-03-30 13:33:29 -07:00
Leonardo de Moura
1a8840330f test: add test for example that does not work in Lean3
cc @eric-wieser
2022-03-30 12:59:55 -07:00
Leonardo de Moura
e53e088be8 test: make it clear the proofs hold by reflexivity 2022-03-30 12:40:30 -07:00
Leonardo de Moura
6056a4cbfa test: stars_and_bars 2022-03-30 12:38:05 -07:00
Leonardo de Moura
b6ce9fa4b1 doc: add palindromes.lean 2022-03-30 11:22:58 -07:00
Leonardo de Moura
df3a8eb126 feat: add helper List.append simp theorems 2022-03-30 11:11:03 -07:00
Leonardo de Moura
c9926b3a8b chore: update stage0 2022-03-29 18:53:47 -07:00
Leonardo de Moura
46ce3013d0 feat: cleanup local context before elaborating match alternatives RHS 2022-03-29 18:52:07 -07:00
Leonardo de Moura
815364768d chore: update stage0 2022-03-29 15:57:45 -07:00
E.W.Ayers
00151f39a1 doc: explain MonadControl 2022-03-29 15:55:08 -07:00
Leonardo de Moura
d1e4712038 fix: smart unfolding
See new comment to understand the issue.

closes #1081
2022-03-29 15:49:14 -07:00
Leonardo de Moura
a8bb7fab93 fix: typo at findRecArg
The code was not traversing the indices if the datatype has parameters
2022-03-29 12:12:43 -07:00
Leonardo de Moura
86432f1833 feat: improve let-pattern and have-pattern macro expansion 2022-03-29 07:33:22 -07:00
Sebastian Ullrich
6dfddbe2e7 feat: quotation precheck for choice nodes 2022-03-29 10:50:11 +02:00
Leonardo de Moura
c7321e0061 chore: remove revert hack from example 2022-03-28 17:18:36 -07:00
Leonardo de Moura
a06cd40e29 feat: improve match expression support at simp 2022-03-28 17:17:01 -07:00
Leonardo de Moura
5ca9b49235 chore: cleanup proof 2022-03-28 14:58:02 -07:00
Leonardo de Moura
2a37f53fca chore: fix core library 2022-03-28 14:32:04 -07:00
Leonardo de Moura
21f7c297e6 chore: update stage0 2022-03-28 14:30:35 -07:00
Leonardo de Moura
3c964f3b9f feat: substitute auxiliary equations introduced by the split tactic 2022-03-28 14:29:28 -07:00
Leonardo de Moura
314bd3ae4c fix: simpH? at match expression equation theorem generator
closes #1080
2022-03-28 12:48:54 -07:00
Leonardo de Moura
2dea5471da feat: add support for HEq to the subst tactic 2022-03-28 12:23:55 -07:00
Leonardo de Moura
334f4f6c85 test: for issue #1079
The error reported on issue #1079 does not happen in the master branch.

closes #1079
2022-03-28 07:19:55 -07:00
Leonardo de Moura
4e008cf8b7 chore: move to tests 2022-03-27 14:57:33 -07:00
Leonardo de Moura
4801b37cfb fix: exfalso 2022-03-27 14:56:24 -07:00
Leonardo de Moura
a2c9b6a8be chore: rename Substate => State.le 2022-03-27 09:30:55 -07:00
Leonardo de Moura
3fe7db1bbf chore: remove dead theorem 2022-03-27 09:15:55 -07:00
Leonardo de Moura
b2ef678199 doc: constant propagation for simple imperative language 2022-03-27 09:02:37 -07:00
Leonardo de Moura
3b7c3c0017 chore: add TODO's 2022-03-26 18:59:43 -07:00
Leonardo de Moura
11ed51dcb2 doc: example for the tutorial 2022-03-26 18:52:53 -07:00
Sebastian Ullrich
85c7772f4c doc: fix ReST markup 2022-03-26 22:50:04 +01:00
Sebastian Ullrich
bef34e30e7 feat: Nix: render examples using LeanInk+Alectryon 2022-03-26 22:50:04 +01:00
Sebastian Ullrich
282147631f chore: Nix: add LeanInk + Alectyron to docs flake 2022-03-26 22:50:04 +01:00
Sebastian Ullrich
19925f8ec1 chore: Nix: move docs build into sub-flake
workflow is not ideal right now because of poor support for sub-flakes,
but I also don't want the doc input in the main flake...
2022-03-26 22:50:04 +01:00
Sebastian Ullrich
4a9bc88a4e chore: fix USE_GMP=OFF by removing GMP linking customization 2022-03-26 16:29:52 +01:00
Sebastian Ullrich
1949b3f676 chore: CI: propagate prepare-llvm failures 2022-03-26 16:29:52 +01:00
Sebastian Ullrich
7ce5b0c4ff feat: CI: build darwin_aarch64 2022-03-26 16:29:52 +01:00
Wojciech Nawrocki
96770b4d83 refactor: remove some code duplication 2022-03-26 06:26:41 -07:00
Wojciech Nawrocki
9223bf3640 feat: environment extension for RPC procedures 2022-03-26 06:26:41 -07:00
Sebastian Ullrich
e3a652de98 chore: CI: fix Linux/aarch64 tarball name, remove cpack config 2022-03-26 10:40:43 +01:00
Leonardo de Moura
c69b4d1f8d chore: update stage0 2022-03-25 19:15:45 -07:00
Leonardo de Moura
a2e467eb32 fix: mkEqnTypes
stop as soon as `lhs` and `rhs` are definitionally equal, and avoid
unnecessary case analysis.

This commit fixes the last issue exposed by #1074

fixes #1074
2022-03-25 19:13:21 -07:00
Leonardo de Moura
3a310fb122 fix: the eta for structures implementation in the elaborator was different from the implementation in the kernel
This issue was exposed by issue #1074
2022-03-25 18:24:15 -07:00
Leonardo de Moura
d4d5d3693e chore: update stage0 2022-03-25 18:18:03 -07:00
Leonardo de Moura
1900efd91a chore: add pp_expr helper function 2022-03-25 18:16:18 -07:00
Leonardo de Moura
7307b02fd7 fix: missing test at has_trivial_structure
see #1074
2022-03-25 17:36:30 -07:00
Sebastian Ullrich
2740cab3fc chore: update RELEASES 2022-03-26 00:02:13 +01:00
Leonardo de Moura
130bbfc501 chore: update README 2022-03-25 14:48:07 -07:00
Leonardo de Moura
9aca413e31 chore: add link to doc/examples 2022-03-25 14:46:43 -07:00
Leonardo de Moura
6da9119516 doc: add Parametric Higher-Order Abstract Syntax example 2022-03-25 14:42:24 -07:00
Sebastian Ullrich
ca9678be58 doc: move tier list to setup.md 2022-03-25 17:45:15 +01:00
Sebastian Ullrich
7ce4a85d25 doc: add platform support tiers to README 2022-03-25 17:45:15 +01:00
Sebastian Ullrich
7e853621eb feat: CI: build linux_aarch64 2022-03-25 17:45:15 +01:00
Leonardo de Moura
e53435979f fix: remove hacky addAutoBoundImplicitsOld 2022-03-25 09:23:43 -07:00
Leonardo de Moura
6631d92d7b fix: addAutoBoundImplicitsOld occurrences at MutualDef.lean and Structure.lean
This commit also fixes non-termination at `collectUnassignedMVars`
2022-03-25 09:07:59 -07:00
Leonardo de Moura
e48cc8901e fix: add new addAutoBoundImplicits that avoids the hack at addAutoBoundImplicitsOld 2022-03-25 08:40:57 -07:00
Leonardo de Moura
519b780164 doc: document InfoTree issue 2022-03-25 07:12:07 -07:00
Leonardo de Moura
370e9c421f fix: bug at deriving Hashable 2022-03-24 18:46:10 -07:00
E.W.Ayers
534aa88188 doc: MetaM 2022-03-24 16:57:42 -07:00
Leonardo de Moura
3c9556ec18 doc: finish deBruijn.lean example 2022-03-24 16:17:53 -07:00
Leonardo de Moura
52a52fbed7 chore: add doc/examples to the test suite 2022-03-24 15:20:18 -07:00
Arthur Paulino
53faa9c8ca doc: restriction of partial functions 2022-03-24 15:01:50 -07:00
E.W.Ayers
90baf14e82 doc: add lib and style changes to lean3changes.md 2022-03-24 15:00:36 -07:00
E.W.Ayers
1e69639fd2 doc: clarify mkLocalDecl 2022-03-24 14:59:46 -07:00
E.W.Ayers
6f5fc72c06 doc: Docstrings for LocalContext.lean 2022-03-24 14:59:46 -07:00
E.W.Ayers
24ebd78071 doc: Expr.lean 2022-03-24 14:52:09 -07:00
Wojciech Nawrocki
8f83c7ab32 feat: user-defined RPC handlers 2022-03-24 08:09:33 -07:00
Sebastian Ullrich
e49949b781 chore: prepare-llvm-linux: fix include path order
should really be `-isystem-after`, but clang ignores it...??
2022-03-24 12:33:33 +01:00
Sebastian Ullrich
75b3012a37 chore: prepare-llvm-linux: stop relying on /usr 2022-03-24 12:33:33 +01:00
Sebastian Ullrich
720e445755 chore: Nix: update inputs 2022-03-24 12:33:33 +01:00
Sebastian Ullrich
5c6e054e24 chore: update to LLVM 14 2022-03-24 12:33:33 +01:00
Leonardo de Moura
fdbe893c40 fix: catch mkAppM exceptions 2022-03-23 17:35:04 -07:00
Leonardo de Moura
96de208a6b chore: remove some partial 2022-03-23 17:16:30 -07:00
Sebastian Ullrich
8a5febf130 chore: CI: fix release job 2022-03-23 19:33:25 +01:00
Leonardo de Moura
be7c71d1c8 chore: update date 2022-03-23 07:44:15 -07:00
Leonardo de Moura
e0aa9fb290 chore: fix typo 2022-03-23 07:39:46 -07:00
Leonardo de Moura
170b911a6f doc: expand deBruijn 2022-03-22 19:35:58 -07:00
Leonardo de Moura
20fb3e470d doc: add dependent de Bruijn indices
TODO: explain example.
2022-03-22 19:11:06 -07:00
Leonardo de Moura
b2a1b88a4e doc: a certified type checker 2022-03-22 19:01:26 -07:00
Leonardo de Moura
a23fcb6033 chore: use github link until we generate the proper webpage using Alectryon 2022-03-22 18:34:40 -07:00
Leonardo de Moura
028e3561e2 fix: link 2022-03-22 18:07:04 -07:00
Leonardo de Moura
265803f7ac doc: fix links 2022-03-22 16:52:08 -07:00
Leonardo de Moura
e06893d1f2 doc: proper TPIL link 2022-03-22 16:37:16 -07:00
Leonardo de Moura
973b76a6e2 doc: add Examples section 2022-03-22 16:35:14 -07:00
Leonardo de Moura
412bc14fbe doc: add well-typed interpreter as an example 2022-03-22 16:32:41 -07:00
Leonardo de Moura
5ae125262b chore: remove C++ coding style from manual 2022-03-22 15:54:51 -07:00
Leonardo de Moura
2e9adf0e04 chore: remove broken documentation 2022-03-22 15:52:13 -07:00
Leonardo de Moura
9d32d7bcf5 test: for issue #1062
closes #1062
2022-03-22 14:14:28 -07:00
Leonardo de Moura
2f67140603 fix: incorrect uses of getMVarType' 2022-03-22 14:11:29 -07:00
Leonardo de Moura
6007147d71 fix: allow universes to be postponed further
closes #1058
2022-03-22 13:57:58 -07:00
Leonardo de Moura
f3b181b972 chore: comment withoutPostponingUniverseConstraints 2022-03-22 13:57:58 -07:00
Mario Carneiro
c29da66c5a fix: annotate binders in intro for hover / go to def 2022-03-22 12:10:51 +00:00
Sebastian Ullrich
3818ea8333 chore: CI: document previous workaround 2022-03-22 12:25:59 +01:00
Sebastian Ullrich
c758d442dc chore: CI: try using the correct C++ compiler for tests on Windows 2022-03-22 12:22:23 +01:00
Sebastian Ullrich
bba0baf92c chore: CI: I'm sure they work fine 2022-03-22 12:22:23 +01:00
Sebastian Ullrich
82049c519c chore: CI: fix MinGW library root 2022-03-22 12:22:23 +01:00
Sebastian Ullrich
00aeaed544 chore: CI: fix manual build 2022-03-22 09:36:52 +01:00
Sebastian Ullrich
c4d3c74837 feat: accept multiple patterns after matches 2022-03-21 17:59:02 +01:00
Sebastian Ullrich
cb93590f0b chore: update stage0 2022-03-21 17:47:03 +01:00
Sebastian Ullrich
faedfbe651 fix: antiquotation splices early in bootstrapping 2022-03-21 17:44:15 +01:00
Leonardo de Moura
3d9e587862 fix: check type mismatch at dependent pattern matching compiler
see issue #1057
2022-03-21 09:28:02 -07:00
Leonardo de Moura
9944feb095 test: use [reducible] 2022-03-21 07:39:44 -07:00
Sebastian Ullrich
89a3f6d623 chore: update Lake 2022-03-21 14:50:54 +01:00
Sebastian Ullrich
1a5822a3e2 chore: update Lake 2022-03-21 14:02:36 +01:00
Leonardo de Moura
3a75cf1920 test: nested inductives 2022-03-21 05:57:02 -07:00
Leonardo de Moura
cba204e3cb chore: update stage0 2022-03-20 18:47:28 -07:00
Leonardo de Moura
321d6b0e67 feat: support for user-defined simp attributes in the simp tactic.
See `RELEASES.md`

TODO: make sure `-thm` also removes `thm` from user-defined simp attributes.
2022-03-20 18:45:57 -07:00
Leonardo de Moura
a2690d5278 feat: improve #eval command 2022-03-20 15:18:47 -07:00
Leonardo de Moura
7b1091770c test: Repr for HList 2022-03-20 15:05:34 -07:00
Leonardo de Moura
6d926c7989 feat: macro expand match alternatives
see #371

This commit does not implement all features discussed in this issue.
It has implemented it as a macro expansion. Thus, the following is
accepted
```lean
inductive StrOrNum where
  | S (s : String)
  | I (i : Int)

def StrOrNum.asString (x : StrOrNum) :=
  match x with
  | I a | S a => toString a
```
It may confuse the Lean LSP server. The `a` on `toString` shows the
information for the first alternative after expansion (i.e., `a` is an `Int`).
After expansion, we have
```
def StrOrNum.asString (x : StrOrNum) :=
  match x with
  | I a => toString a
  | S a => toString a
```
2022-03-20 14:20:13 -07:00
Leonardo de Moura
51ee6fe4f1 chore: fix test 2022-03-20 13:27:19 -07:00
Leonardo de Moura
476bcee8ba chore: update stage0 2022-03-20 13:25:03 -07:00
Leonardo de Moura
8f4d58893f feat: update match parser
Support for
```
def fib (x : Nat) : Nat :=
  match x with
  | 0 | 1 => 1
  | x+2   => fib (x+1) + fib x
```

TODO: expand `matchAlts`
2022-03-20 13:22:39 -07:00
Leonardo de Moura
87bb299f08 feat: add Iterator.atEnd 2022-03-20 11:40:46 -07:00
Leonardo de Moura
4f9dcd55ce chore: update stage0 2022-03-20 10:59:21 -07:00
Leonardo de Moura
3862e7867b refactor: make String.Pos opaque
TODO: this refactoring exposed bugs in `FuzzyMatching` and `Lake`

closes #410
2022-03-20 10:47:13 -07:00
Jakob von Raumer
a91f92c11e feat: allow constants to be type classes
There no reason against constants to be type classes so it is just the check in `addClass` that is needed to be modified.

Closes #1054
2022-03-20 08:03:34 -07:00
Leonardo de Moura
6e94801c00 chore: update stage0 2022-03-19 16:55:26 -07:00
Leonardo de Moura
1b357db3b0 fix: nasty bug at findDeclarationRangesCore?
We must search the environment extension first, and then the builtin
table. Otherwise, the builtin declarations do not change when we
modify the files.

closes #1021
2022-03-19 16:53:22 -07:00
Leonardo de Moura
ed7c8904a9 fix: propagate local and scope modifiers at elab_rules
closes #1039
2022-03-19 16:08:06 -07:00
Leonardo de Moura
82cd5c8eef chore: cleanup 2022-03-19 15:52:04 -07:00
E.W.Ayers
da68f629f9 style: Apply.lean
Apply Leo's review requests.
2022-03-19 15:51:40 -07:00
E.W.Ayers
d954706fcf feat: ApplyNewGoals config for apply
Lean.Meta.Tactic.apply now accepts an ApplyConfig argument.
`apply` now changes which metavariables are stored with choice
of the newGoals config.
This allows one to implement `fapply` and `eapply`.
An example of this is given in tests/lean/run/apply_tac.lean.

Closes #1045
2022-03-19 15:51:40 -07:00
casavaca
bf4ba1583d feat: add simp theorem for List, (as.map f).length = as.length 2022-03-19 11:35:21 -07:00
Leonardo de Moura
72b6f4d528 chore: avoid unnecessary h :s 2022-03-19 11:21:37 -07:00
Leonardo de Moura
f29319647f chore: update stage0 2022-03-19 11:16:24 -07:00
Leonardo de Moura
4f318d3304 test: use dot notation in the example 2022-03-19 10:39:58 -07:00
Leonardo de Moura
d1eb180aae test: add non mutually recursive version 2022-03-19 10:38:39 -07:00
Leonardo de Moura
bdb2e9597a chore: naming convention 2022-03-19 10:20:42 -07:00
Leonardo de Moura
6c8322d20a test: use builtin Char.isDigit and Char.toNat 2022-03-19 10:18:34 -07:00
Leonardo de Moura
a8ddb56e0e chore: cleanup David's example 2022-03-19 10:13:27 -07:00
Leonardo de Moura
c95d5f25a3 feat: convert ites into dites in the WF module
Motivation: the condition is often used in termination proofs.
2022-03-19 10:11:50 -07:00
Leonardo de Moura
9fed5bda7d chore: remove workarounds 2022-03-19 09:44:57 -07:00
Leonardo de Moura
544421faf5 chore: update stage0 2022-03-19 09:43:57 -07:00
Leonardo de Moura
36d955e8cc feat: use simpler encoding for nonmutually recursive definitions 2022-03-19 09:43:18 -07:00
Leonardo de Moura
4b374d4441 fix: Nat/Div.lean, add decreasing_with combinator, and rename decreasing_tactic_trivial 2022-03-19 09:40:10 -07:00
Leonardo de Moura
5e3b3494e2 chore: update stage0 2022-03-19 09:30:34 -07:00
Leonardo de Moura
c7cdbf8ff8 feat: improve auto generated termination_by a bit 2022-03-19 09:28:19 -07:00
Leonardo de Moura
64c5cda612 test: David's lex with string iterators 2022-03-19 09:15:29 -07:00
Leonardo de Moura
9722aeaf32 feat: use String.Iterator.sizeOf_next_lt in the builtin decreasing_tactic 2022-03-19 09:04:40 -07:00
Leonardo de Moura
7dd38a7194 feat: add with_unfolding_all and rfl' tactics 2022-03-19 08:57:04 -07:00
Leonardo de Moura
63e42a8179 chore: fix copyright date
File was created in 2022.
2022-03-19 08:44:21 -07:00
Leonardo de Moura
c8c4d47420 feat: make decreasing_tactic easier to extend 2022-03-19 08:42:38 -07:00
Leonardo de Moura
ef3143e1eb chore: update stage0 2022-03-19 08:39:34 -07:00
Leonardo de Moura
fa74194638 fix: missing s.restore at expandTacticMacroFns 2022-03-19 08:34:54 -07:00
Leonardo de Moura
bd7827ed04 feat: dbg_trace tactic for low-level tactic debugging 2022-03-19 08:25:49 -07:00
Leonardo de Moura
9727387129 feat: helper theorem for proving termination of simple String traversal functions 2022-03-19 07:37:59 -07:00
Leonardo de Moura
ed3c792a4c chore: update stage0 2022-03-19 07:21:52 -07:00
Leonardo de Moura
64bd82dddd feat: custom SizeOf instance for String.Iterator 2022-03-19 07:21:17 -07:00
Leonardo de Moura
4ac88d0eb8 test: lex example from David 2022-03-18 19:53:17 -07:00
Leonardo de Moura
a486503c62 chore: fold Nat literals at reduce 2022-03-18 17:10:46 -07:00
Leonardo de Moura
1514e39006 chore: add double ticks 2022-03-18 17:10:46 -07:00
Leonardo de Moura
42b707e250 perf: improve getMatchWithExtra 2022-03-18 17:10:46 -07:00
Sebastian Ullrich
d5b3430e53 chore: ignore stage0/ (for rg etc.) 2022-03-18 15:28:20 +01:00
Leonardo de Moura
38a1675c72 fix: dicrimination tree getMatchWithExtra
It was buggy when the input argument could be reduced `e`.

fixes #1048
2022-03-17 16:44:38 -07:00
Leonardo de Moura
3193acecfa fix: flush the CoreM and MetaM caches at modifyEnv
This fix may impact performance. Note that we don't need to flush the
cache if we are "adding" stuff to the environment. We only need to
flush the caches if the change is not monotonic. BTW, most of the
changes are monotonic. I think this is why we did not hit this bug before.

We may also move all these caches to an environment extension. It is
an easy way to make sure we preserve the cache when extending the
environment.

I tried a few benchmarks and did not notice a significant difference.

cc @kha @gebner

fixes #1051
2022-03-17 16:02:30 -07:00
Leonardo de Moura
719db55a9c chore: fix trace class 2022-03-17 13:22:16 -07:00
Leonardo de Moura
184b0b8e8d feat: improve "result types must be in the same universe level" error message
The new error message makes it clear why the definition is not accepted.

See issue #1050
2022-03-17 07:41:37 -07:00
zygi
ac793ce196 fix: forward start and stop in Array.allM 2022-03-17 10:08:40 +01:00
Sebastian Ullrich
0d03c6e319 chore: revise non-GMP interface 2022-03-16 17:32:51 -07:00
Daniel Fabian
969eea19f0 refactor: do not use mkAppM so much 2022-03-16 17:21:20 -07:00
Daniel Fabian
cf4e873974 feat: support Sort u in ac_refl. 2022-03-16 17:21:20 -07:00
Daniel Fabian
8e0763f502 fix: binder case. 2022-03-16 17:21:20 -07:00
Daniel Fabian
d667d5ab5d feat: rewrite the tactic using simp as the basis. 2022-03-16 17:21:20 -07:00
Daniel Fabian
ed63274874 refactor: move ac_refl syntaxt to Init/Notation 2022-03-16 17:21:20 -07:00
Daniel Fabian
73a59e5bc4 feat: use simp instead of rewrite inside of ac_refl 2022-03-16 17:21:20 -07:00
Daniel Fabian
fda1c5b192 refactor: simplify proof using <;> 2022-03-16 17:21:20 -07:00
Daniel Fabian
84f72b9389 test: add further ac_refl tests. 2022-03-16 17:21:20 -07:00
Daniel Fabian
a60220b036 feat: add tactic for ac_refl. 2022-03-16 17:21:20 -07:00
Daniel Fabian
eaa48f0d8d refactor: move ac proofs to Init. 2022-03-16 17:21:20 -07:00
Daniel Fabian
1114dfac6c feat: add theory for ac normalization.
This lets us implement an AC reflexivity tactic.
2022-03-16 17:21:20 -07:00
Leonardo de Moura
4320a61f4d chore: use Prod notation in test 2022-03-16 17:14:16 -07:00
Leonardo de Moura
50813429b8 fix: add expected type hint
Other tactics (e.g., `simp_all`) may try to infer the type of the
proof, and `Nat.Linear.eq_of_toNormPoly_eq` has a messy resulting type.
2022-03-16 17:07:22 -07:00
Leonardo de Moura
cb925a3a3c fix: return some at simpCnstrPos? if arith expr was normalized, but not simplified
Example: converted `<`, `>`, or `>=` into `<=`.
2022-03-16 16:36:39 -07:00
Leonardo de Moura
9b9ed6db68 feat: add simp_all_arith macro 2022-03-16 16:17:45 -07:00
Leonardo de Moura
4ba5a9b041 fix: bug at KExprMap 2022-03-16 16:07:14 -07:00
Leonardo de Moura
09648521d1 chore: add Repr instances 2022-03-16 16:07:14 -07:00
Sebastian Ullrich
4fd520e902 feat: generalize inferred namespace notation to functions 2022-03-16 23:40:05 +01:00
Leonardo de Moura
68154a6c69 test: add Pos view 2022-03-16 10:08:43 -07:00
Leonardo de Moura
05a2778b0d fix: ensure explicit pattern variables provided by the uses are indeed pattern variables 2022-03-16 07:50:29 -07:00
Leonardo de Moura
90c442da76 feat: add internal option for communicating to the delaborator that input term is a pattern 2022-03-16 07:50:29 -07:00
Sebastian Ullrich
a3c73f5df8 chore: remove orphan file 2022-03-16 10:25:18 +01:00
Leonardo de Moura
0a2d0bc3fd chore: update stage0 2022-03-15 17:43:52 -07:00
Leonardo de Moura
0bd9de1cb9 perf: add InstantiateLevelCaches for types and values at CoreM 2022-03-15 17:42:38 -07:00
Leonardo de Moura
d6de53a7aa perf: custom splitAnd 2022-03-15 16:59:11 -07:00
Leonardo de Moura
b8a4f3a7a3 perf: quick filter for simpMatch when proving equation theorems 2022-03-15 15:53:29 -07:00
Leonardo de Moura
e44b36cab0 chore: cleanup optimization using Lean bitwise operators 2022-03-15 12:06:08 -07:00
Leonardo de Moura
49e33fdb23 chore: fix tests 2022-03-15 11:35:47 -07:00
Leonardo de Moura
e1ba83d902 chore: update stage0 2022-03-15 11:31:39 -07:00
Leonardo de Moura
d3e2dfb079 perf: optimize mkApp 2022-03-15 11:31:15 -07:00
Leonardo de Moura
9d73317d76 perf: faster Expr.data 2022-03-15 11:30:41 -07:00
Leonardo de Moura
d2dc38fdb6 perf: use HasConstCache to minimize the number of visited terms at Structural and WF
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
2022-03-15 08:40:47 -07:00
Leonardo de Moura
5283007aa4 feat: add HasConstCache 2022-03-15 08:39:48 -07:00
Leonardo de Moura
3278d7bc2a chore: update stage0 2022-03-15 07:16:17 -07:00
Leonardo de Moura
ca6453a0ab perf: efficient unsigned hash(expr const & e) 2022-03-15 07:15:00 -07:00
Leonardo de Moura
eccd5c11c9 perf: removeUnusedEqnHypotheses 2022-03-15 06:53:43 -07:00
Leonardo de Moura
2b71bc84f3 perf: try injection before contradiction at mkSplitterProof 2022-03-15 05:37:10 -07:00
Leonardo de Moura
c3c0b8b8a2 chore: remove unnecessary code 2022-03-15 05:26:33 -07:00
Leonardo de Moura
aa68057c85 chore: more general type universes in example 2022-03-15 05:19:02 -07:00
Leonardo de Moura
7ee7ca30b8 fix: index out of bounds 2022-03-15 05:16:19 -07:00
Leonardo de Moura
4e261b15e5 fix: smart unfolding bug in over applications 2022-03-14 19:17:21 -07:00
Leonardo de Moura
eb7539ef77 fix: mkEqnTypes overapplied lhs in equational theorems
This issue was exposed by the "Dependent de Bruijn indices" from CPDT.
2022-03-14 17:42:21 -07:00
Leonardo de Moura
c6dae18787 chore: add helper theorems 2022-03-14 16:24:05 -07:00
Leonardo de Moura
40f608bfbd chore: cleanup String.extract reference implementation 2022-03-14 16:23:13 -07:00
Leonardo de Moura
8e29747fe7 feat: add simp theorem (a : Nat) : (a ≤ 0) = (a = 0) 2022-03-14 15:43:42 -07:00
Leonardo de Moura
bbe6bd4e72 chore: simplify String.utf8ByteSize reference implementation 2022-03-14 15:42:58 -07:00
Leonardo de Moura
14ed473777 feat: mark Nat.zero_le as simp theorem 2022-03-14 15:19:52 -07:00
Leonardo de Moura
7fda1f47f8 test: add test for issue fixed in previous commit 2022-03-14 14:11:08 -07:00
Leonardo de Moura
86fc089e07 fix: tryAutoCongrTheorem? may still use dsimp for fixed arguments
Reviewed-by: Leonardo de Moura <leonardo@microsoft.com>
2022-03-14 14:04:28 -07:00
Leonardo de Moura
ef154ec0cf test: add TreeNode example using for in notation 2022-03-14 11:52:54 -07:00
Leonardo de Moura
cab3217b05 feat: add forIn'_eq_forIn theorem for lists 2022-03-14 11:50:47 -07:00
Leonardo de Moura
2ac9cfb7b1 fix: eta expand partial applications of recursive function being defined 2022-03-14 10:05:33 -07:00
Leonardo de Moura
801552e1ac chore: fix tests 2022-03-14 10:05:33 -07:00
Leonardo de Moura
9988faf8bd fix: missing mkRecAppWithSyntax 2022-03-14 10:05:33 -07:00
Leonardo de Moura
02145f66cf chore: fix typo 2022-03-14 10:05:33 -07:00
Sebastian Ullrich
147a5c2933 chore: prefer LEAN_SRC_PATH 2022-03-14 17:24:25 +01:00
Leonardo de Moura
d2cc5b4a83 chore: fix test 2022-03-13 15:53:21 -07:00
Leonardo de Moura
fa0964c07e fix: preserve variable name at WF decreasing goals when function has only one non fixed argument 2022-03-13 13:20:07 -07:00
Leonardo de Moura
060be7e7ec fix: :: is infix right 2022-03-13 09:25:56 -07:00
Leonardo de Moura
672a889c83 test: add hlist pattern match example 2022-03-13 09:15:55 -07:00
Leonardo de Moura
30c153aa76 chore: update stage0 2022-03-12 20:18:20 -08:00
Leonardo de Moura
bfe57a1cb0 chore: simplify definition 2022-03-12 20:16:45 -08:00
Leonardo de Moura
231120c118 chore: update RELEASES.md 2022-03-12 20:02:39 -08:00
Leonardo de Moura
5707cab7bf feat: improve #eval command
Now, if it fails to synthesize the TC instance, it applies `whnf` and
tries again.
2022-03-12 19:55:15 -08:00
Leonardo de Moura
3cd41acd14 test: HList with notation overloads 2022-03-12 19:47:57 -08:00
Leonardo de Moura
af5a24140a test: simple type checker at CPDT 2022-03-12 18:44:52 -08:00
Leonardo de Moura
7e3519a3a2 test: add CPDT first example 2022-03-12 17:06:20 -08:00
Leonardo de Moura
f0c31d7e28 feat: allow rw to unfold nonrecursive definitions too 2022-03-12 15:44:52 -08:00
Leonardo de Moura
c0a72172f1 chore: update stage0 2022-03-12 15:35:09 -08:00
Leonardo de Moura
7af09ac009 refactor: move equation theorem cache to Meta/Eqns.lean 2022-03-12 15:34:32 -08:00
Leonardo de Moura
cf0ca026fb feat: equation theorems at rw 2022-03-12 13:53:02 -08:00
Leonardo de Moura
9d1dbada79 feat: only try to generate equation theorems for definitions whose types are not propositions 2022-03-12 13:44:33 -08:00
Leonardo de Moura
8a46668884 chore: update stage0 2022-03-12 10:46:17 -08:00
Leonardo de Moura
a6bfefe5bd fix: nasty performance problem at isDefEq
This problem was originally exposed by the `Array.eraseIdxAux`.
2022-03-12 10:44:43 -08:00
Leonardo de Moura
eddcedb58c fix: pattern normalization code 2022-03-12 06:07:04 -08:00
Lars
95cf18457d chore: address review comments 2022-03-12 13:25:35 +00:00
Sebastian Ullrich
82c682d385 chore: remove redundant proof 2022-03-12 11:12:56 +01:00
Leonardo de Moura
a4f47adf9e fix: normalize method at Match.lean 2022-03-11 18:19:37 -08:00
Leonardo de Moura
63dcf2124c chore: add link to quickstart to README 2022-03-11 16:35:07 -08:00
Chris Lovett
6dc576121d doc: replace quickstart leanpkg info with info about lake 2022-03-11 16:31:58 -08:00
Leonardo de Moura
15e30a93f3 feat: update RELEASES.md 2022-03-11 16:28:01 -08:00
larsk21
e430496903 doc: fix fuzzy matching docs 2022-03-11 16:25:26 -08:00
larsk21
ea5b6d568f fix: review suggestions + code structure 2022-03-11 16:25:26 -08:00
larsk21
0ef3ea4bc9 feat: enable fuzzy matching for workspace symbols 2022-03-11 16:25:26 -08:00
larsk21
64dba41b4c feat: enable fuzzy matching for completion 2022-03-11 16:25:26 -08:00
Sebastian Ullrich
ff11325fce perf: use mkArray in fuzzyMatchCore 2022-03-11 16:25:26 -08:00
Sebastian Ullrich
d48c5b99e9 perf: eliminate MProd allocations in iterateLookaround 2022-03-11 16:25:26 -08:00
Sebastian Ullrich
896b9b48a3 perf: eliminate some allocations in iterateLookaround 2022-03-11 16:25:26 -08:00
Sebastian Ullrich
7106d3fb34 perf: specialize iterateLookaround 2022-03-11 16:25:26 -08:00
larsk21
135eac71a1 feat: add string fuzzy matching 2022-03-11 16:25:26 -08:00
Leonardo de Moura
5caf1bc692 chore: style
Use `·` instead of `.` for structuring tactics.
2022-03-11 16:12:46 -08:00
Leonardo de Moura
ddf93d2f8a feat: support for arrow types in the dot notation
cc @gebner
2022-03-11 15:39:41 -08:00
Leonardo de Moura
8d42978e63 feat: generate error message when induction tactic is used on a nested inductive type without specifying an eliminator 2022-03-11 14:45:57 -08:00
Leonardo de Moura
712e9b7d45 chore: add custom induction principle for LazyList 2022-03-11 14:21:35 -08:00
Leonardo de Moura
7d5da95434 fix: remove unused hypotheses from conditional equation theorems 2022-03-11 14:10:57 -08:00
Leonardo de Moura
54b74796f6 feat: use tryContradiction at mkUnfoldProof 2022-03-11 12:52:15 -08:00
Leonardo de Moura
272dd5533f chore: style use · instead of . for lambda dot notation
We are considering removing `.` as an alternative for `·` in the
lambda dot notation (e.g., `(·+·)`).
Reasons:
- `.` is not a perfect replacement for `·` (e.g., `(·.insert ·)`)
- `.` is too overloaded: `(f.x)` and `(f .x)` and `(f . x)`. We want to keep the first two.
2022-03-11 07:49:03 -08:00
Leonardo de Moura
2364bc7b46 chore: add link to issue 2022-03-10 17:10:12 -08:00
Leonardo de Moura
002412e9d0 chore: missing code block annotation 2022-03-10 17:08:54 -08:00
Leonardo de Moura
1b5e9c7c83 chore: use new notation on its own implementation 2022-03-10 16:56:39 -08:00
Leonardo de Moura
61cd3dcc32 chore: update stage0 2022-03-10 16:55:40 -08:00
Leonardo de Moura
e1fa9c131c feat: inferring namespace from expected type a la Swift
Now that `PatternVars.lean` has been redesigned, it is feasible to
implement issue #944.

closes #944
2022-03-10 16:55:25 -08:00
Leonardo de Moura
7a7841fa95 chore: update stage0 2022-03-10 16:07:25 -08:00
Leonardo de Moura
1c99fe92ac feat: add dotIdent parser
see #944
2022-03-10 16:04:41 -08:00
Leonardo de Moura
3214a20d33 feat: allow overloaded notation in patterns 2022-03-10 12:51:34 -08:00
Leonardo de Moura
fddc8b06ac fix: missing case at getStuckMVar?
Fix issue reported at
https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/'rewrite'.20failed.20but.20it.20should.20work/near/274870747
2022-03-10 10:33:11 -08:00
Leonardo de Moura
92318d07bb feat: add MonadBacktrack instance for CollectPatternVars.M monad 2022-03-10 10:23:18 -08:00
Leonardo de Moura
7a39be225d refactor: move methods to MetaM 2022-03-10 10:00:46 -08:00
Leonardo de Moura
2fb9a39cb4 refactor: implement MonadQuotation at CoreM 2022-03-10 09:55:20 -08:00
Leonardo de Moura
3edb0ede04 chore: update stage0 2022-03-10 08:56:06 -08:00
Leonardo de Moura
7850dc023b fix: make sure the structure instance notation does not leak auxiliary type annotations (e.g., autoParam and optParam) 2022-03-10 08:41:00 -08:00
Leonardo de Moura
c1b1a916eb doc: update release notes 2022-03-10 08:26:27 -08:00
Leonardo de Moura
efc89eb4e1 fix: make sure inferProjType consume auxiliary type annotations 2022-03-10 08:15:34 -08:00
Leonardo de Moura
0ef8aaeda0 feat: make sure minor premises in recursors do not include auxiliary type annotations (e.g., autoParam and optParam) 2022-03-10 08:08:36 -08:00
Leonardo de Moura
1afee372f7 refactor: move consume_type_annotations declaration to expr.h 2022-03-10 08:00:39 -08:00
Leonardo de Moura
33883e9d2a fix: resulting type of projection functions should not include auxiliary type annotations (e.g., autoParam) 2022-03-10 07:47:38 -08:00
Leonardo de Moura
5825eb394f refactor: move isOutParam to Expr.lean, rename consumeAutoOptParam => consumeTypeAnnotations 2022-03-10 07:37:41 -08:00
Leonardo de Moura
38668308ef fix: do not rename metavariables that are already in the patternVars array
It fixes a regression introduced yesterday.
2022-03-10 05:53:54 -08:00
Leonardo de Moura
9c5f6361a3 doc: document the new pattern elaboration procedure 2022-03-09 18:58:23 -08:00
Leonardo de Moura
ca253c43e1 refactor: pattern elaboration
We don't use the following hack anymore:
-  /- HACK: `fvarId` is not in the scope of `mvarId`
-     If this generates problems in the future, we should update the metavariable declarations. -/
-  assignExprMVar mvarId (mkFVar fvarId)

This hack was corrupting the `InfoTree`.
2022-03-09 18:19:14 -08:00
Leonardo de Moura
b0246172fa chore: add comment and remove dbg trace message 2022-03-09 14:02:30 -08:00
Leonardo de Moura
b6dc3dda04 chore: fix tests 2022-03-09 14:02:13 -08:00
Leonardo de Moura
caa1366b62 fea: erase nested inaccessible annotations 2022-03-09 14:01:59 -08:00
Leonardo de Moura
1609f96128 refactor: simplify PatternVar.lean and Match.lean 2022-03-09 14:01:40 -08:00
Leonardo de Moura
74411aa472 fix: do not display implicit fields 2022-03-09 12:33:22 -08:00
Leonardo de Moura
50ae170bcc feat: allow mkLambdaFVars and mkForallFVars to abstract unassigned metavars too 2022-03-09 11:27:58 -08:00
Leonardo de Moura
4660485ac8 refactor: collectDeps => collectForwardDeps 2022-03-09 11:27:58 -08:00
Leonardo de Moura
5636c94cd0 chore: remove old comment, simplify exception 2022-03-09 11:27:58 -08:00
Leonardo de Moura
1263cea6af feat: add support for unassigned metavariables at dependsOn 2022-03-09 11:27:58 -08:00
Sebastian Ullrich
db9b963af7 chore: Nix: adjust message 2022-03-09 10:31:32 +01:00
Sebastian Ullrich
202258cc87 chore: Nix: remove debug flag 2022-03-09 10:30:37 +01:00
Sebastian Ullrich
a7438e9eae chore: Nix: remove debug flag 2022-03-09 10:30:09 +01:00
Sebastian Ullrich
7821a201e9 chore: Nix: update Nix 2022-03-09 10:29:25 +01:00
Sebastian Ullrich
126c7dd4ea chore: Nix: command for (one-time) linking .ileans 2022-03-09 10:29:25 +01:00
Sebastian Ullrich
2221cc8141 chore: Nix: emulate lake serve 2022-03-09 10:14:43 +01:00
Leonardo de Moura
164f07a5e5 feat: generalize Expr.abstractRange
It now takes free variables **and** metavariables.
This is the first step to make `mkForallFVars` and `mkLambdaFVars`
more general.
2022-03-08 18:19:17 -08:00
Leonardo de Moura
d6b782f811 chore: remove workaround
for regression introduced by the following change

* Auto implicit behavior changed for inductive families. An auto implicit argument occurring in inductive family index is also treated as an index (IF it is not fixed, see next item)
2022-03-08 17:58:20 -08:00
Leonardo de Moura
3b7ada0b35 chore: update stage0 2022-03-08 17:58:20 -08:00
Leonardo de Moura
4ee131981d feat: in an inductive family the longest fixed prefix of indices is now promoted to parameters
This modification is relevant for fixing regressions on recent changes
to the auto implicit behavior for inductive families.

The following declarations are now accepted:
```lean
inductive HasType : Fin n → Vector Ty n → Ty → Type where
  | stop : HasType 0 (ty :: ctx) ty
  | pop  : HasType k ctx ty → HasType k.succ (u :: ctx) ty

inductive Sublist : List α → List α → Prop
  | slnil : Sublist [] []
  | cons l₁ l₂ a : Sublist l₁ l₂ → Sublist l₁ (a :: l₂)
  | cons2 l₁ l₂ a : Sublist l₁ l₂ → Sublist (a :: l₁) (a :: l₂)

inductive Lst : Type u → Type u
  | nil  : Lst α
  | cons : α → Lst α → Lst α
```

TODO: universe inference for `inductive` should be improved. The
current approach is not good enough when we have auto implicits.

TODO: allow implicit fixed indices that do not depend on indices that
cannot be moved to become parameters.
2022-03-08 17:56:34 -08:00
Leonardo de Moura
234046521a feat: print number of parameters for an inductive type 2022-03-08 17:48:46 -08:00
Leonardo de Moura
7b84b4cdaa fix: improve inductive indices elaboration
TODO: convert fixed indices to parameters. Motivation: types such as
```lean
inductive Foo : List α → Type
  | mk : Foo []
```
Users should not need to write
```lean
inductive Foo {α} : List α → Type
  | mk : Foo []
```
2022-03-08 17:48:46 -08:00
Leonardo de Moura
f74513384e refactor: cleanup addAutoBoundImplicits 2022-03-08 17:48:46 -08:00
Sebastian Ullrich
e9b8e54dcc feat: scientific parser alias for scientificLit 2022-03-08 18:54:05 +01:00
Sebastian Ullrich
dca5da6b18 chore: update RELEASES.md 2022-03-07 17:28:51 +01:00
Jonathan Coates
11cce61e4d chore: Clean up LSP folding a little
- Wait for all terms to be elaborated before showing folding regions.
   May want to change this to support partial results.
 - Use .span to extract import statements, rather than mutually
   recursive functions.
 - Some tiny other bits of cleanup
2022-03-07 17:23:35 +01:00
Jonathan Coates
04e60cebd1 feat: LSP code folding support
The following constructs are foldable:
 - Sections and namespaces
 - Blocks of import/open statements
 - Multi-line commands (so mostly definitions)
 - Mutual definitions
 - Module-level doc comments
 - Top-level definition doc comments

Fixes #1012
2022-03-07 17:23:35 +01:00
Sebastian Ullrich
dc8367d1f5 chore: CI: adjust nightly release time 2022-03-07 15:39:58 +01:00
Sebastian Ullrich
f2d5470f19 feat: allow interpretation of constants initialized by native code 2022-03-07 10:59:49 +01:00
Sebastian Ullrich
ff097e952f chore: link orphan file 2022-03-07 10:59:49 +01:00
Leonardo de Moura
dddfb65660 test: use notation 2022-03-06 19:28:01 -08:00
Leonardo de Moura
7c5604996a test: unfoldr 2022-03-06 19:26:04 -08:00
Leonardo de Moura
619186b2a8 feat: only use set_option codegen false where needed 2022-03-06 19:15:05 -08:00
Leonardo de Moura
10bccfe501 test: remove workaround 2022-03-06 13:58:42 -08:00
Leonardo de Moura
46d1111d3d fix: typo at unfoldBothDefEq 2022-03-06 13:54:42 -08:00
Leonardo de Moura
ff0f3bfc61 fix: interaction between overloaded notation and delayed coercions
The new test exposes this issue.
2022-03-06 09:49:15 -08:00
Leonardo de Moura
e9909020e8 test: add delay helper contructor 2022-03-06 08:08:51 -08:00
Leonardo de Moura
ad4b1796a0 chore: update stage0 2022-03-06 08:01:23 -08:00
Leonardo de Moura
b664a93d8e fix: a match application is stuck if one of the discriminants contain metavariables 2022-03-06 07:51:09 -08:00
Leonardo de Moura
8bcaafb28b fix: universe metavariables should not be taken into account at getKeyArgs 2022-03-06 07:50:19 -08:00
Leonardo de Moura
b105c006a5 fix: PrefixTree WellFormed type
`β` is a parameter.
2022-03-06 07:30:34 -08:00
Leonardo de Moura
1450a86c4d feat: include types in the "ambiguous, possible interpretations" error message 2022-03-06 07:26:31 -08:00
Leonardo de Moura
d9a6680536 doc: describe the auto implicit chaining in the release notes 2022-03-05 17:45:56 -08:00
Leonardo de Moura
d3b2028a05 feat: add Fin.succ 2022-03-05 17:36:38 -08:00
Leonardo de Moura
3f9c854194 feat: auto local implicit chaining 2022-03-05 17:30:15 -08:00
Leonardo de Moura
f7130d8e07 refactor: use CPS at addAutoBoundImplicits
We want to be able to declare new local variables there.
2022-03-05 16:24:33 -08:00
Leonardo de Moura
22731c02b0 fix: auto implicit locals in inductive families 2022-03-05 15:47:20 -08:00
Leonardo de Moura
613cf19509 fix: discrimination trees and "stuck" terms
See comments and new test.
2022-03-05 15:12:20 -08:00
Leonardo de Moura
d39102f865 fix: smart unfolding for reducible definitions
When `TransparencyMode.reducible`, smart unfolding for reducible
definitions was not being used.
2022-03-05 14:42:47 -08:00
Leonardo de Moura
9e76cd7d65 fix: toName function at elabAppFnId
closes #1038
2022-03-04 16:56:02 -08:00
Leonardo de Moura
a670ed1e2d fix: use withoutErrToSorry at apply
closes #1037
2022-03-04 14:36:10 -08:00
Leonardo de Moura
a2457110db chore: update RELEASES.md 2022-03-03 20:05:58 -08:00
Leonardo de Moura
82b056aa75 chore: fix test 2022-03-03 19:53:35 -08:00
Leonardo de Moura
8b248e2d8c feat: elaborate for h : x in xs do ... notation 2022-03-03 19:52:26 -08:00
Leonardo de Moura
ef38c82c77 fix: missing hypotheses at List.sizeOf_lt_of_mem 2022-03-03 19:52:05 -08:00
Leonardo de Moura
99677823c3 fix: ForIn' instance binder annotations 2022-03-03 19:51:45 -08:00
Leonardo de Moura
b4ddcd600b chore: fix test 2022-03-03 19:15:07 -08:00
Leonardo de Moura
538eee0b6a chore: update stage0 2022-03-03 19:11:27 -08:00
Leonardo de Moura
5d2420b1c9 chore: add auxiliary notation for ForIn' 2022-03-03 19:10:24 -08:00
Leonardo de Moura
d8ee03c1bb feat: add ForIn' instance that is similar to ForIn but provides a proof that the iterated elements are in the collection 2022-03-03 19:05:27 -08:00
Leonardo de Moura
7462e3ad52 chore: update stage0 2022-03-03 18:29:04 -08:00
Leonardo de Moura
92937b3aba feat: add for h : x in xs do ... notation
The idea is to have `h : x \in xs`.
This commit just adds the parser.
2022-03-03 18:27:40 -08:00
Leonardo de Moura
51ec4522fe fix: documentation 2022-03-03 18:18:37 -08:00
Leonardo de Moura
e1424653b9 chore: remove workaround 2022-03-03 18:16:54 -08:00
Leonardo de Moura
0847c59667 chore: update stage0 2022-03-03 18:13:34 -08:00
Leonardo de Moura
b745c4f51a fix: recursive overapplication at WF/Fix.lean 2022-03-03 18:13:34 -08:00
Leonardo de Moura
f306c9b69b fix: split tactic
`unreachable!` assertions at `simpIfLocalDecl` and
`simpTargetLocalDecl` were reachable.
2022-03-03 18:13:34 -08:00
Leonardo de Moura
f4e98be163 fix: use whnfD at mkNoConfusion
The `split` tactic failed at `Array.sizeOf_lt_of_mem` because the type
in the equality is `Id Bool` when we write `true` instead of `id true`.
2022-03-03 18:13:34 -08:00
Leonardo de Moura
337c55f322 fix: missing import 2022-03-03 18:13:34 -08:00
Leonardo de Moura
4657d47c16 chore: fix tests 2022-03-03 18:13:34 -08:00
Leonardo de Moura
aeb9b2fb8c chore: add Membership instance for Array 2022-03-03 18:13:34 -08:00
Leonardo de Moura
fd519401ff feat: add Membership instance for List
and the theorem `a ∈ as -> sizeOf a < sizeOf as`.
We will use theorems like this one to improve the `decreasing_tactic`.
2022-03-03 18:13:21 -08:00
Leonardo de Moura
022a4d5ac1 feat: add notation 2022-03-03 17:18:51 -08:00
Leonardo de Moura
f629be745b chore: add Nat.le_refl as simp theorem 2022-03-03 17:18:11 -08:00
Leonardo de Moura
89c3820781 chore: naming convention 2022-03-03 17:17:51 -08:00
Leonardo de Moura
5845002e8c feat: use WF at anyM 2022-03-03 16:43:05 -08:00
Leonardo de Moura
3fa001911b feat: add ite_self simp theorem 2022-03-03 11:55:05 -08:00
Leonardo de Moura
e4fa3e5d83 chore: add link to RELEASES.md 2022-03-03 11:31:24 -08:00
Leonardo de Moura
30409fc73d chore: add example to RELEASES.md 2022-03-03 11:28:37 -08:00
Leonardo de Moura
02d7cedba8 chore: remove unnecessary termination_by annotations 2022-03-03 11:24:06 -08:00
Leonardo de Moura
35c587afbf chore: update stage0 2022-03-03 11:17:35 -08:00
Leonardo de Moura
137c70f055 chore: add LinearArith/Nat/Solver.lean 2022-03-03 11:13:40 -08:00
Leonardo de Moura
043d338271 feat: add getForbiddenByTrivialSizeOf 2022-03-03 11:12:32 -08:00
Leonardo de Moura
1f2618adba feat: delaborate cond using bif-then-else 2022-03-03 07:41:39 -08:00
Leonardo de Moura
8dd76868ff test: plan for supporting combinators (e.g., List.foldl) in WF recursion 2022-03-02 15:18:25 -08:00
Leonardo de Moura
e091e7fb30 test: simplify proofs 2022-03-02 13:57:43 -08:00
Leonardo de Moura
4ba97c22ec test: proving properties of mutually defined functions 2022-03-02 13:40:19 -08:00
Leonardo de Moura
1155d52702 chore: update TODO comment 2022-03-02 12:51:46 -08:00
Leonardo de Moura
14ef4b4304 test: add WF test that exposes the need for better error messages 2022-03-02 12:47:19 -08:00
Leonardo de Moura
093ab49b7f feat: improve generateElements a bit 2022-03-02 11:58:47 -08:00
Leonardo de Moura
52403fca83 feat: add support for guessing (very) simple WF relations
There are a lot of TODOs, but it is already useful for simple cases.

closes #847
2022-03-02 11:52:00 -08:00
Leonardo de Moura
99204d2226 refactor: modify elabWFRel to CPS 2022-03-02 11:52:00 -08:00
Leonardo de Moura
88a2645a5f refactor: add Lean/Meta/Tactic/LinearArith/Basic.lean 2022-03-02 11:52:00 -08:00
Leonardo de Moura
f171286e74 refactor: add src/Lean/Meta/Tactic/LinearArith/Nat 2022-03-02 11:52:00 -08:00
Sebastian Ullrich
c9713b1b69 fix: setExpectedFn 2022-03-02 16:28:53 +01:00
Leonardo de Moura
7eba003f53 chore: style 2022-03-01 18:54:10 -08:00
Leonardo de Moura
ca5696330c doc: update RELEASES.md 2022-03-01 18:51:15 -08:00
Leonardo de Moura
1e205d635e fix: bug at wfRecursion
"After compilation" attributes were being applied to soon when we did
not need to generate auxiliary functions.
2022-03-01 17:48:06 -08:00
Leonardo de Moura
bb2de82cb6 chore: update stage0 2022-03-01 17:47:40 -08:00
Leonardo de Moura
2daf8d62ac test: LazyList with Thunk 2022-03-01 16:55:56 -08:00
Leonardo de Moura
eac5bab429 chore: helper theorem 2022-03-01 16:54:25 -08:00
Leonardo de Moura
5dba98327c chore: update stage0 2022-03-01 16:41:28 -08:00
Leonardo de Moura
140559c447 feat: sizeOf for Thunks and Unit -> a 2022-03-01 16:40:11 -08:00
Leonardo de Moura
de51160929 fix: core library 2022-03-01 13:36:24 -08:00
François G. Dorais
e84699f130 fix: remove unnecessary hypotheses 2022-03-01 13:31:01 -08:00
Leonardo de Moura
e85abb6292 chore: update stage0 2022-03-01 13:25:54 -08:00
Leonardo de Moura
89e0de9fbb chore: use WF compiler to define Nat.mod and Nat.div 2022-03-01 13:08:59 -08:00
Leonardo de Moura
f16d8acb29 feat: eager normalization for proofs by reflection 2022-03-01 12:43:55 -08:00
Leonardo de Moura
0f796ac804 chore: avoid heterogeneous polymorphic operations and add add hugeFuel at Linear.lean 2022-03-01 11:25:15 -08:00
Leonardo de Moura
9bd82b798a chore: use bif instead of if at Linear.lean 2022-03-01 10:55:03 -08:00
Leonardo de Moura
0158c2eeb7 chore: update stage0 2022-03-01 09:03:20 -08:00
Leonardo de Moura
da55789c26 feat: add a proper BEq instance for Nat 2022-03-01 09:01:08 -08:00
Leonardo de Moura
85a1a5233b chore: workaround for compiler closed term extraction issue 2022-03-01 09:01:08 -08:00
Leonardo de Moura
5948003601 feat: add support for constant folding Nat.beq, Nat.blt, and Nat.ble 2022-03-01 09:01:08 -08:00
Gabriel Ebner
a7c9d2735f fix: do not apply eta for structures in Prop
The eta-expansion contains invalid projections, and the eta-rule is
subsumed by proof irrelevance anyhow.
2022-03-01 09:00:46 -08:00
Gabriel Ebner
3746005f5f fix: reject projection (_ : ∃ x, p).2
The inferred type of this projection does not even type check, in general.
2022-03-01 09:00:46 -08:00
Leonardo de Moura
0f06fbf648 feat: LawfulBEq must be reflexive 2022-02-28 19:27:51 -08:00
Leonardo de Moura
ecca71f0f5 chore: update stage0 2022-02-28 18:39:24 -08:00
Leonardo de Moura
7a49f71328 feat: add bif notation for cond function 2022-02-28 18:34:59 -08:00
Leonardo de Moura
4e310ac63d feat: improve SimpTheorem preprocessor 2022-02-28 18:27:36 -08:00
Leonardo de Moura
e8fb0c96ac feat: add helper theorems 2022-02-28 18:06:02 -08:00
Leonardo de Moura
5ddb3c3435 feat: faster PolyCnstr.combine 2022-02-28 17:24:26 -08:00
Leonardo de Moura
adf3510e08 chore: increase maxHeartbeats default values
We now increase the number of heartbeats at `expr_eq_fn`. Thus, the
old default values are too small.
2022-02-28 15:44:08 -08:00
Leonardo de Moura
b5f28239af feat: add List helper theorems 2022-02-28 15:16:13 -08:00
Leonardo de Moura
998a3de747 chore: update stage0 2022-02-28 15:13:38 -08:00
Leonardo de Moura
3005bab970 feat: helper theorem and tactic for WF 2022-02-28 15:11:00 -08:00
Leonardo de Moura
55bc048656 feat: make sure inequalities are normalized when no monomial was cancelled 2022-02-28 15:10:39 -08:00
Leonardo de Moura
e455df9c95 fix: use a def-eq aware mapping at toLinearExpr
The new test exposes the problem fixed by this commit.
In the termination proof we have two `sizeOf xs` terms that are not
syntactically identical (only definitional equal) because the
instances are different.
2022-02-28 13:46:36 -08:00
Leonardo de Moura
802922ddaf feat: add helper sizeOf simp theorems 2022-02-28 12:28:37 -08:00
Leonardo de Moura
2ba3205f94 feat: add Prod.Lex.right' 2022-02-28 11:19:28 -08:00
Leonardo de Moura
10657f5e81 feat: add trace <string> tactic 2022-02-28 11:16:42 -08:00
Leonardo de Moura
63a5cd5056 fix: trace_state messages should not be lost during backtracking 2022-02-28 11:07:41 -08:00
Leonardo de Moura
d89fa9d4c3 fix: endPos missing at trace messages 2022-02-28 10:55:45 -08:00
Leonardo de Moura
b7d2239ca4 chore: update stage0 2022-02-28 08:32:24 -08:00
Leonardo de Moura
46b97c2b70 fix: ExceptT.run_lift 2022-02-28 07:25:00 -08:00
Sebastian Ullrich
53d313c74c chore: fix function name 2022-02-28 16:16:22 +01:00
Leonardo de Moura
c5fdd54cd8 feat: support for acyclicity at unifyEqs
closes #1022
2022-02-27 10:03:40 -08:00
Leonardo de Moura
89f88b1caa feat: simplify nested arith expressions 2022-02-27 09:01:52 -08:00
Leonardo de Moura
c5baf759e2 fix: we must use addAsAxiom before getFixedPrefix
`getFixedPrefix` uses `isDefEq`, and it will fail if it needs to
retrieve the type of one of the recursive function being defined.
2022-02-27 09:01:52 -08:00
Leonardo de Moura
2c00823da9 test: simp_arith 2022-02-27 09:01:52 -08:00
Sebastian Ullrich
6c6f66b812 feat: propagate actual file name in file worker
Also stop recreating the FileMap for every command, that's quadratic!
2022-02-27 10:33:27 +01:00
Leonardo de Moura
90055fb7d4 chore: clarify error message at decreasing_tactic 2022-02-26 10:15:05 -08:00
Leonardo de Moura
f22b48b226 fix: display all remaining goals at fail tactic error message 2022-02-26 09:49:06 -08:00
Leonardo de Moura
f7f886dcb2 feat: improve error message for decreasing_tactic failures 2022-02-26 09:42:59 -08:00
Leonardo de Moura
cabd599de1 feat: add fail tactic 2022-02-26 09:31:19 -08:00
Leonardo de Moura
0242eb7ede feat: use simp (config := { arith := true }) at decreasing_tactic
closes #262
2022-02-26 09:12:34 -08:00
Leonardo de Moura
ff76958959 feat: basic support for linear Nat arithmetic at simp 2022-02-26 08:58:32 -08:00
Leonardo de Moura
41a5c2bce4 feat: add support for negation at simpCnstr? 2022-02-25 18:30:09 -08:00
Leonardo de Moura
5030e613a2 feat: add isSimpCnstrTarget 2022-02-25 17:18:50 -08:00
Leonardo de Moura
7217ee7754 fix: GE.ge and GT.gt support at simpCnstr? 2022-02-25 17:12:27 -08:00
Leonardo de Moura
812cc72285 chore: add helper theorems 2022-02-25 17:04:04 -08:00
Leonardo de Moura
0681d818ec chore: add helper function for simp 2022-02-25 16:42:41 -08:00
Leonardo de Moura
38da48c5cf refactor: LinearArith/Basic.lean => LinearArith/Solver.lean 2022-02-25 16:35:36 -08:00
Leonardo de Moura
cd710e903e chore: update stage0 2022-02-25 16:32:03 -08:00
Leonardo de Moura
77dda12bc9 chore: add Simp.Config.arith option 2022-02-25 16:30:44 -08:00
Leonardo de Moura
3f636b9f83 feat: add Lean.Meta.Linear.Nat.simpCnstr? 2022-02-25 16:27:21 -08:00
Leonardo de Moura
f7fd706973 chore: missing import 2022-02-25 16:20:26 -08:00
Leonardo de Moura
346930af9d feat: add ExprCnstr.eq_of_toNormPoly_eq 2022-02-25 14:55:20 -08:00
Leonardo de Moura
b8bed6fb5c feat: add LawfulBEq class 2022-02-25 13:35:08 -08:00
Leonardo de Moura
3b130ee42f feat: add Poly.toExpr 2022-02-25 12:31:30 -08:00
Leonardo de Moura
7d8cb84834 chore: update stage0 2022-02-25 08:50:05 -08:00
Leonardo de Moura
049273afee fix: add workarounds to code generator
The issue is only going to be properly fixed when we rewrite `csimp`
in Lean. The `csimp` performs transformations that do not preserve
typability, but it also uses the kernel `infer_type` which assumes the
input is type correct. In the new `csimp`, we must have a different
`infer_type` which returns an `Any` type in this kind of situation.

The workaround in this commit simply disables optimizations when
`infer_type` fails. It does not fix all occurrences of this problem,
but the two places that issue #1030 triggered.

closes #1030
2022-02-25 08:47:56 -08:00
Leonardo de Moura
4f7067fe7f fix: substEqs may close input goal
closes #1029
2022-02-25 08:07:23 -08:00
Leonardo de Moura
82e3789604 fix: run_lift type 2022-02-25 07:49:34 -08:00
Leonardo de Moura
7920db9521 feat: check for invalid projections during elaboration
It produces a better error message than the one produced by the
kernel.
2022-02-25 07:43:37 -08:00
Leonardo de Moura
04b93fc725 chore: fix invalid proof 2022-02-25 07:24:02 -08:00
Leonardo de Moura
0611eb84cc chore: update stage0 2022-02-25 07:22:59 -08:00
Leonardo de Moura
c9471ea029 fix: invalid proof 2022-02-25 07:17:31 -08:00
Leonardo de Moura
db38bc4043 fix: missing check at infer_proj
We should not allow `h.1` if `h` is a proposition and the result is
not. The recursor for `h`'s type can only eliminate into `Prop`.
2022-02-25 07:15:34 -08:00
Leonardo de Moura
622995b2c7 chore: style 2022-02-24 17:57:21 -08:00
Leonardo de Moura
e04ad112b2 fix: store levelNames in the SavedContext 2022-02-24 17:47:26 -08:00
Leonardo de Moura
be2e2cb70e chore: adjust proofs affected by update stage0 2022-02-24 17:20:17 -08:00
Leonardo de Moura
7480670c6a chore: update stage0 2022-02-24 17:18:42 -08:00
Leonardo de Moura
2961e9cbf0 fix: heuristic for deciding which additional propositions must be included in equality theorems 2022-02-24 17:17:07 -08:00
Leonardo de Moura
bdea43a52a feat: while and repeat macros 2022-02-24 16:26:07 -08:00
Leonardo de Moura
f7f04483b1 feat: add src/Lean/Meta/Tactic/LinearArith/Nat.lean 2022-02-24 15:24:59 -08:00
Leonardo de Moura
bd3ad35a1c fix: we may get False in unreachable branches 2022-02-24 15:24:07 -08:00
Leonardo de Moura
8131aa5a64 chore: add simp theorem heq_eq_eq 2022-02-24 13:45:34 -08:00
Leonardo de Moura
b134b9a3a4 chore: move isNatProjInst 2022-02-24 13:45:34 -08:00
Leonardo de Moura
a430b2ad71 chore: add copyright 2022-02-24 13:45:34 -08:00
Leonardo de Moura
05be43455a feat: add src/Init/Data/Nat/Linear.lean 2022-02-24 13:45:17 -08:00
Leonardo de Moura
43c2169f78 fix: when performing contextual simplification, and arrow may become a dependent arrow
fixes #1024
2022-02-23 18:43:32 -08:00
Leonardo de Moura
49c64040a2 feat: add support for HEq at injections tactic 2022-02-23 17:31:17 -08:00
Leonardo de Moura
07d1ec1926 fix: simp_all was "self-simplifying" simplified hypotheses
fixes #1027
2022-02-23 16:48:28 -08:00
Leonardo de Moura
16b8800607 chore: fix tests 2022-02-23 16:30:27 -08:00
Leonardo de Moura
0125db40a2 fix: remove [..] annotation from if simp theorems
fixes #1025
2022-02-23 16:28:12 -08:00
Leonardo de Moura
3e0ea7fbae fix: use instantiateMVars before invoking pure function findIfToSplit 2022-02-23 16:25:33 -08:00
Leonardo de Moura
a1366fcb3b chore: cleanup 2022-02-23 16:24:42 -08:00
Leonardo de Moura
c491659970 feat: improve split tactic error message 2022-02-23 16:00:42 -08:00
Leonardo de Moura
902e60c480 feat: add Format.isEmpty 2022-02-23 13:34:25 -08:00
Leonardo de Moura
52b53ab7a2 fix: heuristic for generating equation theorem types
closes #1026
2022-02-23 13:10:30 -08:00
Leonardo de Moura
2340f1b9bd feat: add isBRecOnRecursor 2022-02-23 13:09:29 -08:00
Leonardo de Moura
15546fbc48 feat: add Expr.findExt? 2022-02-23 12:32:17 -08:00
Leonardo de Moura
1ac9c1263b test: add helper theorems 2022-02-23 11:52:03 -08:00
Leonardo de Moura
dbe9bf61c5 fix: unfold auxiliary theorems created by decreasing_tactic 2022-02-23 09:02:23 -08:00
Leonardo de Moura
4794b9709f feat: improve equation theorem and match-splitter generation at MatchEqns.lean 2022-02-22 17:43:42 -08:00
Leonardo de Moura
52ff840321 feat: support for HEq at injection 2022-02-22 17:24:11 -08:00
Leonardo de Moura
c9f8ec71df fix: invalid rewrite when proving equation theorems for declaration using well-founded recursion 2022-02-22 16:38:51 -08:00
Leonardo de Moura
d36027d2fa test: add Certificate.of_combine_isUnsat 2022-02-22 16:04:23 -08:00
Leonardo de Moura
24249fecd3 feat: helper simp theorems 2022-02-22 16:03:36 -08:00
Leonardo de Moura
8d6750469e chore: helper Nat theorems 2022-02-22 14:26:50 -08:00
Leonardo de Moura
77fc0d3223 test: cleanup 2022-02-22 07:23:07 -08:00
Leonardo de Moura
c932d9d33c test: combine two inequalities 2022-02-21 15:13:37 -08:00
Leonardo de Moura
c73d177c94 perf: simpH? at MatchEqns.lean 2022-02-21 12:04:03 -08:00
Leonardo de Moura
0e40c63292 chore: fix typo 2022-02-21 10:55:38 -08:00
Leonardo de Moura
e9ee8ee86f test: add cancelation theorems for <= and < 2022-02-21 08:49:50 -08:00
Leonardo de Moura
7f3a3138d0 feat: helper Nat theorems 2022-02-21 08:49:50 -08:00
Sebastian Ullrich
d39c23f061 feat: quot precheck for 2022-02-21 10:14:39 +01:00
Leonardo de Moura
0986696758 test: add cancelation example 2022-02-20 17:35:33 -08:00
Leonardo de Moura
a8427702e8 test: reverse direction for cancelation procedure 2022-02-20 17:03:11 -08:00
Leonardo de Moura
33b1d2fd98 fix: preserve arrow binder names and info at simp
We use the idiom `revert; simp; ...; intro` in a few places. Some of
the reverted hypotheses manifest themselves as arrows in the target.
Before this commit, `simp` would lose the binder names and info when
simplifying an arrow, and we would get inaccessible names when
reintroducing them.
2022-02-20 16:27:40 -08:00
Leonardo de Moura
4ccab41819 test: proof by reflection example 2022-02-20 10:11:40 -08:00
Leonardo de Moura
cf0f7a30c4 test: add Monomials.cancel 2022-02-19 21:29:33 -08:00
Leonardo de Moura
ba16903205 feat: add helper theorems 2022-02-19 21:25:44 -08:00
Leonardo de Moura
855b71299f test: arith by reflection 2022-02-19 17:54:32 -08:00
Leonardo de Moura
193859c72c feat: add helper theorems 2022-02-19 17:53:54 -08:00
Leonardo de Moura
7a13eaea8d chore: update stage0 2022-02-19 08:11:17 -08:00
Leonardo de Moura
7a81589c49 feat: improve "constant approximation" heuristic used at isDefEq 2022-02-19 08:09:31 -08:00
Leonardo de Moura
19bcb5fb31 feat: add Array.popWhile and Array.takeWhile 2022-02-19 07:04:52 -08:00
Leonardo de Moura
a4d6cbfedd feat: improve match elaborator 2022-02-19 06:12:21 -08:00
Leonardo de Moura
f64f563936 chore: fix comment 2022-02-19 06:11:53 -08:00
Leonardo de Moura
e61d0be561 feat: isolate fixed prefix at well-founded recursion
closes #1017
2022-02-18 10:40:32 -08:00
Leonardo de Moura
75e771b6e8 feat: add support for fixed argument prefix at mkFix and elabWFRel
This is needed for #1017

TODO: `addNonRecPreDefs` and equation theorems
2022-02-18 07:59:32 -08:00
Leonardo de Moura
70312191f7 feat: make sure packDomain and packMutual ignore the fixed arguments
TODO: adapt `elabWFRel`, `mkFix`, and etc.

This is needed for #1017
2022-02-17 17:43:06 -08:00
Leonardo de Moura
9ee529e5ce fix: use PSum instead of Sum when using well-founded recursion
See new test for example that did not work with `Sum` because type
alpha was `Sort u`.
2022-02-17 16:14:34 -08:00
Leonardo de Moura
4a0ae8326c feat: compute the fixed prefix size for mutually recursive definitions 2022-02-17 14:12:05 -08:00
Leonardo de Moura
3f0be7901e chore: update stage0 2022-02-17 10:52:34 -08:00
Leonardo de Moura
dedb6ee01b fix: skip value if type is computationally irrelevant 2022-02-17 10:41:16 -08:00
Leonardo de Moura
ba0904060b chore: missing trace_pp_expr 2022-02-17 10:40:21 -08:00
Leonardo de Moura
4ed5c8405b feat: improve IR checker error messages 2022-02-17 09:51:05 -08:00
Leonardo de Moura
6b1297fe85 chore: update stage0 2022-02-16 13:52:28 -08:00
Xubai Wang
ca521e1188 feat: add position to mod doc 2022-02-16 13:50:19 -08:00
Leonardo de Moura
373a64ee09 test: for isNoncomputable 2022-02-16 13:37:49 -08:00
Leonardo de Moura
9d6c26a4a6 chore: update stage0 2022-02-16 13:33:33 -08:00
Leonardo de Moura
e1d9dc4b38 feat: store noncomputable declarations 2022-02-16 13:33:02 -08:00
Leonardo de Moura
31e90c8f65 chore: update stage0 2022-02-16 13:22:44 -08:00
Leonardo de Moura
4ba1e0ad4b feat: add isNoncomputable function for querying whether a given declaration has been marked as "noncomputable" by users 2022-02-16 13:20:31 -08:00
Leonardo de Moura
ad5099ec3c fix: mkLetRecClosureFor for nested let-recs
closes #1020
2022-02-16 12:44:02 -08:00
Leonardo de Moura
86328bcb9f feat: tail recursive List.iota and [csimp] theorem 2022-02-16 11:25:46 -08:00
Leonardo de Moura
d46d246cd9 fix: documentation 2022-02-15 16:19:35 -08:00
Leonardo de Moura
80bb1454c5 doc: add example to RELEASES.md 2022-02-15 16:09:36 -08:00
Leonardo de Moura
3f4d8f370a fix: backtrack InfoTree when backtracking at the discriminant refinement method
This commit addresses issue described at https://github.com/leanprover/lean4/issues/1018#issuecomment-1040597212

closes #1018
2022-02-15 16:01:09 -08:00
Leonardo de Moura
fd9165415e feat: try to preserve variable names during discriminant refinement
This fixes second issue at #1018
2022-02-15 15:54:03 -08:00
Leonardo de Moura
56cdacfc28 feat: allow synthetic holes to be used as patterns
They are useful for getting meaningful pattern variable names when the hole
is not an inaccessible pattern. See new test.

We are going to use this feature to address issue 2 at #1018.
2022-02-15 15:34:14 -08:00
Leonardo de Moura
da1a327d13 chore: remove old comment 2022-02-15 15:01:26 -08:00
Leonardo de Moura
1f230c336b chore: style 2022-02-15 13:32:48 -08:00
Leonardo de Moura
045527daac chore: update stage0 2022-02-15 12:23:11 -08:00
Leonardo de Moura
2435119e6a chore: update stage0 2022-02-15 12:20:34 -08:00
Leonardo de Moura
993ec54db6 chore: avoid hack that may introduce unnecessary dependencies 2022-02-15 12:17:40 -08:00
Leonardo de Moura
e07823bb12 chore: remove unnecessary partial
TODO: we should generate an error/warning when `partial` is not necessary
2022-02-15 12:16:49 -08:00
Leonardo de Moura
a2613a36a4 fix: incorrect dependencies due to assigned variables 2022-02-15 12:15:45 -08:00
Leonardo de Moura
bd89bdde8a fix: core library
see #1018
2022-02-15 12:12:56 -08:00
Leonardo de Moura
df584567f5 feat: (generalizing := true) is the default behavior for match-expressions
closes #1018
2022-02-15 11:12:04 -08:00
Sebastian Ullrich
e9ee9204c4 chore: update Lake 2022-02-15 19:19:19 +01:00
Sebastian Ullrich
54522006f4 refactor: List.get: take Fin to align with Array.get
/cc @leodemoura
2022-02-15 18:41:22 +01:00
Leonardo de Moura
d1e5e4166a feat: use sorry instead of trying to synthesize Inhabited at error recovery 2022-02-15 09:15:18 -08:00
Leonardo de Moura
f75fdcb19b feat: when Lean cannot prove termination, then report error and add definition as partial, and if it fails add as axiom 2022-02-15 07:44:27 -08:00
Sebastian Ullrich
4b03666ecc chore: include orphan file 2022-02-15 09:44:19 +01:00
Leonardo de Moura
f33cb27d1c doc: update RELEASES.md 2022-02-14 15:58:58 -08:00
Leonardo de Moura
66e0b72c6f test: notation for providing names to equality proofs in match expressions is not whitespace sensitivity anymore 2022-02-14 15:51:23 -08:00
Leonardo de Moura
409530306c chore: update stage0 2022-02-14 15:48:11 -08:00
Leonardo de Moura
764a1d9f51 chore: fix tests 2022-02-14 15:47:12 -08:00
Leonardo de Moura
c67ee9fdf4 feat: add pp annotation for match parser 2022-02-14 15:46:52 -08:00
Leonardo de Moura
ffca6975f2 chore: remove bootstrapping workarounds 2022-02-14 15:39:21 -08:00
Leonardo de Moura
42c80c7483 feat: remove whitespace sensitivity at match discriminants 2022-02-14 15:37:40 -08:00
Leonardo de Moura
2a2ad75faa chore: update stage0 2022-02-14 15:37:01 -08:00
Leonardo de Moura
93b5b74b36 feat: modify notation for providing motive in "match" expressions 2022-02-14 15:36:14 -08:00
Leonardo de Moura
0030208d99 chore: prepare to change builtin syntax 2022-02-14 14:17:24 -08:00
Leonardo de Moura
a0fb412989 chore: update stage0
Make sure previous fix is also applied to enumeration types in the
core library.
2022-02-14 12:06:42 -08:00
Leonardo de Moura
07043e73b0 chore: fix tests 2022-02-14 12:06:03 -08:00
Leonardo de Moura
aa63fda835 fix: mark auxiliary noConfusion declarations for enumeration types as [reducible]
closes #1016
2022-02-14 12:03:49 -08:00
Leonardo de Moura
ee9fcd30e8 fix: mark Nat.decEq as [reducible]
It is used by the `noConfusionType` construction for enumeration types,
and we want it to reduce even when the reducibility setting is
`TransparencyMode.reducible` as for other inductive types.

see issue #1016
2022-02-14 12:00:29 -08:00
Leonardo de Moura
93d5351fba feat: display reducibility status at #print 2022-02-14 11:52:41 -08:00
Leonardo de Moura
420d0f2a3f fix: make sure noConfusionTypeEnum and noConfusionEnum fully reduce even reducibility setting is set to TransparencyMode.reducible
The previous definition would not fully reduce since `ite` and `dite`
are not tagged as `[reducible]`.

see issue #1016
2022-02-14 11:39:18 -08:00
Sebastian Ullrich
bdbffdaaf7 chore: update Lake 2022-02-14 16:52:54 +01:00
ammkrn
3de18ceb55 doc: document match h:e with syntax 2022-02-14 15:53:37 +01:00
Sebastian Ullrich
340c331da9 chore: CI: ignore diff exit code 2022-02-13 00:04:08 +01:00
Leonardo de Moura
8be916b0cf doc: update RELEASES.md 2022-02-12 12:08:01 -08:00
Leonardo de Moura
82bce7ebec fix: declare local instaces occurring in patterns 2022-02-12 12:01:08 -08:00
Leonardo de Moura
32dd3c6b29 feat: use at least default transparency at toCtorWhenK
Improves the effectiveness of `simp` when reducing `match`-expr.
2022-02-12 07:56:45 -08:00
Leonardo de Moura
999e80745e test: add test for already fixed issue reported on Zulip 2022-02-12 07:53:31 -08:00
Leonardo de Moura
0649e5fa8a feat: Basic model-based solver for linear arithmetic 2022-02-11 18:38:33 -08:00
Leonardo de Moura
37afafad6e feat: missing Rat functions 2022-02-11 18:24:18 -08:00
Leonardo de Moura
e8c23cdf7e feat: add cache at Lean/Elab/PreDefinition/WF/PackDomain.lean 2022-02-11 09:52:14 -08:00
Leonardo de Moura
9cfa728eac chore: remove workaround for issue #1013 2022-02-11 09:32:29 -08:00
Leonardo de Moura
7b3a674555 chore: update stage0 2022-02-11 09:31:02 -08:00
Leonardo de Moura
ab41dd0d83 test: add test for issue #1013 2022-02-11 09:28:46 -08:00
Leonardo de Moura
123e0f42e9 feat: support partial and over applications at WF/PackDomain.lean
closes #1013
2022-02-11 09:28:17 -08:00
Sebastian Ullrich
2390691116 chore: remove obsolete workaround 2022-02-11 18:19:59 +01:00
Sebastian Ullrich
80e2e1daa8 test: mutual block not needed 2022-02-11 16:22:13 +01:00
Sebastian Ullrich
c460a2e404 chore: CI: fail when uploading 0 files 2022-02-11 10:11:45 +01:00
Sebastian Ullrich
589f05d2c8 chore: CI: do not delete nightly artifacts before uploading them 2022-02-11 10:02:54 +01:00
Leonardo de Moura
77bbaf82df feat: decidable equality for arrays 2022-02-10 17:31:03 -08:00
Leonardo de Moura
a2b7ff9e0d chore: fix doc 2022-02-10 17:12:18 -08:00
Leonardo de Moura
712d6726e4 feat: rename tactic byCases => by_cases 2022-02-10 17:11:07 -08:00
Leonardo de Moura
1491253479 feat: helper simp theorems 2022-02-10 17:06:16 -08:00
Leonardo de Moura
1d5da63482 chore: simplify Array.isEqvAux 2022-02-10 16:51:47 -08:00
Leonardo de Moura
6b6c44c559 feat: add helper lemma 2022-02-10 16:51:32 -08:00
Sebastian Ullrich
894dc0e1b8 fix: pretty-printing match dependent on let 2022-02-10 10:19:04 +01:00
Leonardo de Moura
54473ad523 test: add missing test for issue #998 2022-02-09 18:02:01 -08:00
Leonardo de Moura
9fe0d28107 fix: do not split on if-then-else terms when generating equation theorems
Reason: avoid unnecessary case-analysis explosion
It is also unnecessary since we only refine the `below` and `F`
arguments over `match`-expressions.

This fixes the last case at issue #998
```
attribute [simp] BinaryHeap.heapifyDown
```

closes #998
2022-02-09 17:43:35 -08:00
Leonardo de Moura
c685a2d9ed feat: add splitIte flag to splitTarget? tactic 2022-02-09 17:38:04 -08:00
Leonardo de Moura
7fc12014da fix: make sure splitTarget? skips match expressions that produce type errors at splitMatch
We can now generate the equation theorem for
```
attribute [simp] Array.heapSort.loop
```

see #998
2022-02-09 17:07:10 -08:00
Leonardo de Moura
e574c5373f feat: improve delta? method
Use zeta reduction to create new opportunities of beta-reduction.

This issue fixes on the problems that were affecting the generation of
equation theorems for `Array.heapSort.loop` (see issue: #998).
After this fix, the equation theorem generation fails at `splitMatch`.
2022-02-09 13:31:55 -08:00
Sebastian Ullrich
8cbd7ccf09 test: reimplement package tests using Lake 2022-02-09 12:21:11 -08:00
Leonardo de Moura
15e6dd262d chore: fix tests 2022-02-09 10:13:52 -08:00
Leonardo de Moura
8fbe7062fa fix: preserve unused let-decls at Meta.transform 2022-02-09 10:13:52 -08:00
Leonardo de Moura
3b67c7db81 fix: handling of letrec declarations in the well-founded recursion module 2022-02-09 10:13:52 -08:00
Leonardo de Moura
471ef75345 feat: improve test at packDomain 2022-02-09 10:13:52 -08:00
Leonardo de Moura
e66575d4fc refactor: move and generalize ensureNoRecFn 2022-02-09 10:13:52 -08:00
Leonardo de Moura
1cfe403edf chore: style 2022-02-09 10:13:52 -08:00
Sebastian Ullrich
9e11ea3b34 chore: move test to correct folder 2022-02-09 14:32:18 +01:00
Sebastian Ullrich
a8e34b9310 test: mutual recursion over mutual inductive 2022-02-09 14:24:45 +01:00
Sebastian Ullrich
bdf9472069 chore: fix changelog path... 2022-02-09 09:42:17 +01:00
Leonardo de Moura
2ef0146140 fix: avoid unnecessary matcheApp.addArgs at BRecOn and Fix
It fixes the following two cases from #998
```
attribute [simp] Lean.Export.exportName
attribute [simp] Lean.Export.exportLevel
```
2022-02-08 15:06:14 -08:00
Leonardo de Moura
8692225432 fix: saveEqn at Lean/Elab/PreDefinition/Eqns.lean
see #998
2022-02-08 13:44:49 -08:00
Leonardo de Moura
33ed496661 feat: improve contradiction 2022-02-08 13:26:05 -08:00
Leonardo de Moura
3367f0b06a feat: use splitTarget? when proving equation theorems for recursive definitions 2022-02-08 12:53:09 -08:00
Leonardo de Moura
afb5cb16ee chore: simplify option names
see #1011
2022-02-08 12:23:24 -08:00
Leonardo de Moura
59acf01bc9 feat: relax auto-implicit restrictions
The new options `relaxedAutoBoundImplicitLocal` can be used to
disable this feature.

closes #1011
2022-02-08 12:17:42 -08:00
Leonardo de Moura
398b9c136a chore: fix test 2022-02-08 11:43:45 -08:00
Leonardo de Moura
96336bb44d test: add tests for #998
The previous changes fixed two of them.
2022-02-08 11:43:45 -08:00
Leonardo de Moura
c486203481 fix: use simpTargetStar when proving equation theorems for recursive definitions
Add `take` function reported at Zulip.
2022-02-08 11:43:45 -08:00
Leonardo de Moura
c1777c17e3 feat: add simpTargetStar 2022-02-08 11:43:45 -08:00
Leonardo de Moura
824d0aa8a5 chore: remove leftover 2022-02-08 11:43:45 -08:00
Sebastian Ullrich
ad80c69cba chore: CI: add RELEASES.md diff to nightly description 2022-02-08 14:25:54 +01:00
Sebastian Ullrich
e45830f8b3 chore: CI: release only if all jobs finished successfully 2022-02-08 14:25:54 +01:00
Leonardo de Moura
e626b3d4aa chore: make it clear that v4.0.0-m4 has not been released yet 2022-02-07 17:59:46 -08:00
Leonardo de Moura
a9bb646d4f chore: cleanup 2022-02-07 17:35:07 -08:00
Leonardo de Moura
aa2d547c2b doc: add last item at congr theorem whishlist
closes #988
2022-02-07 17:26:43 -08:00
Leonardo de Moura
8d7f0ea2f2 feat: add removeUnnecessaryCasts
see #988
2022-02-07 17:24:32 -08:00
Leonardo de Moura
9d34d9bc5a feat: cache and optimize mkCongrSimp? at simp
see #988
2022-02-07 17:01:21 -08:00
Leonardo de Moura
007f0e1d71 feat: use mkCongrSimp? at simp
TODO: cache auto generated congr theorems, and `removeUnnecessaryCasts`

see #988
2022-02-07 16:45:01 -08:00
Leonardo de Moura
93bd4a7f88 chore: lemma => thm 2022-02-07 13:55:23 -08:00
Leonardo de Moura
6f7fb9ccaf chore: update stage0 2022-02-07 13:19:52 -08:00
Leonardo de Moura
5baac1905f fix: use private names for theorems that are created on demand
closes #1006
2022-02-07 13:16:22 -08:00
ammkrn
efb533fb24 doc: document some do block patterns/sugar 2022-02-07 20:50:15 +01:00
Leonardo de Moura
eff63632b3 feat: improve error message when max heartbeats is reached during TC
see #1007
2022-02-07 11:23:48 -08:00
Gabriel Ebner
f8b43630a6 fix: refs to copied subobjects in diamond extension 2022-02-07 10:54:32 -08:00
Sebastian Ullrich
4e77b6a615 doc: extend RELEASES.md 2022-02-07 11:31:58 +01:00
Leonardo de Moura
e8781ad889 chore: update stage0 2022-02-06 09:17:40 -08:00
Leonardo de Moura
8cea32f42d chore: fix test 2022-02-06 09:15:39 -08:00
Leonardo de Moura
9c2942c36d chore: "simp lemma" => "simp theorem" 2022-02-06 09:15:39 -08:00
Leonardo de Moura
d6dc077c86 refactor: CongrLemma => SimpCongrTheorem 2022-02-06 09:15:39 -08:00
Leonardo de Moura
96bae46045 refactor: SimpLemma => SimpTheorem 2022-02-06 09:15:39 -08:00
Sebastian Ullrich
2c7d67d498 fix: make info of fields synthesized by structure update synthetic 2022-02-06 08:50:07 -08:00
Leonardo de Moura
255db2b47d chore: update stage0 2022-02-06 08:12:21 -08:00
Joscha
196cf67eed fix: handle overlapping definitions 2022-02-06 16:52:18 +01:00
Leonardo de Moura
f78d355416 chore: style 2022-02-06 07:29:26 -08:00
Leonardo de Moura
e35235eec5 chore: update stage0 2022-02-06 07:24:22 -08:00
Sebastian Ullrich
0ef5985b5f fix: binder info range for let rec/where 2022-02-06 07:21:51 -08:00
Patrick Stevens
b48e48328f chore: Nix: bump vscode-lean4 version to 0.0.63 2022-02-05 20:08:45 +01:00
Joscha
841d51a7e6 fix: walkDir 2022-02-05 19:55:09 +01:00
Sebastian Ullrich
06e81637fe fix: symlinking src/ into build directory 2022-02-05 18:52:40 +01:00
Leonardo de Moura
7f0060b214 chore: update stage0 2022-02-04 18:25:35 -08:00
Leonardo de Moura
6de0b1fc67 feat: add mkCongrSimp.mkProof
see #988
2022-02-04 17:57:28 -08:00
Leonardo de Moura
3ae455bccf feat: add mkCongrSimp?
TODO: proof is still missing

see #988
2022-02-04 17:57:28 -08:00
Leonardo de Moura
a028a69159 feat: cache isProp and isDecInst at FunInfo 2022-02-04 17:57:28 -08:00
Wojciech Nawrocki
5668e2644a fix: typo 2022-02-04 12:55:53 -08:00
Sebastian Ullrich
a7ba103e0a chore: remove leanpkg 2022-02-04 19:03:40 +01:00
Sebastian Ullrich
2b7427c962 chore: adjust changelog merge strategy config
/cc @leodemoura
2022-02-04 18:32:20 +01:00
Leonardo de Moura
cfb67ee589 chore: add RELEASES.md
It is based on the approach used in rust.
2022-02-04 09:24:20 -08:00
Sebastian Ullrich
ae062c6ead fix: match tactic should not trigger implicit lambdas 2022-02-04 07:55:56 -08:00
Sebastian Ullrich
7fd76cd1b9 chore: CI: fix sanitizer test excludes
Apparently StackOverflow got fixed at some point?
2022-02-04 15:01:30 +01:00
Mario Carneiro
6e7d76f4d8 fix: typo 2022-02-03 18:21:14 -08:00
Leonardo de Moura
95aec2cf93 chore: update stage0 2022-02-03 18:10:10 -08:00
Leonardo de Moura
1684cfec83 chore: update lake 2022-02-03 18:09:48 -08:00
Leonardo de Moura
12e2a79170 chore: fix codebase after removing auto pure 2022-02-03 18:08:14 -08:00
Leonardo de Moura
00f59a91ee chore: update stage0 2022-02-03 17:07:14 -08:00
Leonardo de Moura
e9d85f49e6 chore: remove tryPureCoe?
Based on the discussion at
https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/for.2C.20unexpected.20need.20for.20type.20ascription/near/269083574
The consensus seemed to be that "auto pure" is more confusing than its worth.
2022-02-03 16:25:24 -08:00
Leonardo de Moura
6d07092d1e chore: update stage0 2022-02-03 15:56:28 -08:00
Leonardo de Moura
5f74cd4968 feat: add let pat := val | elseCase do-notation 2022-02-03 15:55:03 -08:00
Leonardo de Moura
420f5bb315 fix: hide internal namespaces from autocompletion
closes #993
2022-02-03 13:33:27 -08:00
Leonardo de Moura
17eab845ed fix: improve tryPostponeIfMVar
see #992
2022-02-03 13:24:19 -08:00
Leonardo de Moura
2bc5b8d1ec chore: remove doc/changes.md
In the last dev meeting, we have decided we are not going to use it.
We will release often (every month), and use pull requests and issues
to report changes.
2022-02-03 09:23:45 -08:00
Leonardo de Moura
42b3ed5903 test: add Pi.single test
see #988
2022-02-03 09:22:22 -08:00
Sebastian Ullrich
22526051e0 fix: install sources to src/lean/, not lib/lean
Not only is this more semantically appropriate (see e.g.
`/usr/src/{linux,rust,...}` on Debian), it also prevents .ilean files
from Lake tests (which are symlinked into the build directory as part of
`src/` during development) from ending up in the built-in LEAN_PATH and
being watched & loaded by the server.
2022-02-03 18:20:21 +01:00
Gabriel Ebner
55be278cd7 fix: ensure motive of matches is Bool 2022-02-03 18:17:27 +01:00
Gabriel Ebner
54cff10f3f fix: dependent fields in diamond extensions 2022-02-03 09:17:14 -08:00
Leonardo de Moura
c30380e2fa feat: lift the restriction in congr theorems that all function arguments on the lhs must be free variables
see #988
2022-02-02 18:23:18 -08:00
Leonardo de Moura
b7c853692d test: add test for decide congruence issue
TODO: congruence lemma must be automatically generated.

see #988
2022-02-02 17:49:03 -08:00
Leonardo de Moura
101fc12b54 feat: partially applied user congruence lemmas
see #988
2022-02-02 17:41:21 -08:00
Leonardo de Moura
dbb6dcd9a9 fix: remove irrelevant hypotheses in auto-generated equation theorems 2022-02-02 15:39:51 -08:00
Leonardo de Moura
188f0eb70f fix: splitMatch tactic
Improve how we compute the motive for match-splitter eliminator.

closes #986
2022-02-02 15:06:03 -08:00
Leonardo de Moura
d7f085976f feat: add Coe MVarId MessageData 2022-02-02 15:06:03 -08:00
Leonardo de Moura
4a4074baab fix: only generalize when needed at cases 2022-02-02 15:06:03 -08:00
Leonardo de Moura
4fe56d2a9d fix: allow mkElimApp to assign new goals when solving typing constraints 2022-02-02 15:06:03 -08:00
Leonardo de Moura
65e1fc1211 feat: at splitMatch only generalize discriminants that are not FVar 2022-02-02 15:06:03 -08:00
Leonardo de Moura
630bf4e129 chore: update error message for throwNestedTacticEx 2022-02-02 15:06:03 -08:00
Leonardo de Moura
3101b98f50 feat: used nested tactic exception at splitMatch 2022-02-02 15:06:03 -08:00
Sebastian Ullrich
16f6b19e21 fix: silence .ilean load errors 2022-02-02 22:02:15 +01:00
Sebastian Ullrich
e400b02a05 test: wrong test 2022-02-02 13:17:30 +01:00
Sebastian Ullrich
3425278d97 test: forgot to commit test for #801 2022-02-02 13:08:23 +01:00
larsk21
ce92672c3a fix: remove explicit Ord Range 2022-02-02 13:03:21 +01:00
larsk21
e73645505b fix: remove duplicate from interactive highlight test 2022-02-02 13:03:21 +01:00
larsk21
6cee7a6a31 fix: dedup references in findModuleRefs 2022-02-02 13:03:21 +01:00
larsk21
818e8acd0e feat: add test for handleDocumentHighlight 2022-02-02 13:03:21 +01:00
larsk21
bc65da2e83 feat: extend handleDocumentHighlight 2022-02-02 13:03:21 +01:00
Leonardo de Moura
3dfd14dfff chore: fix test 2022-01-31 16:45:57 -08:00
Leonardo de Moura
b1617fe04c feat: add throwNestedTacticEx
closes #194
2022-01-31 16:25:44 -08:00
Leonardo de Moura
ccddd0d932 feat: show proof state/unclosed goal message on empty tactic sequences
closes #361
2022-01-31 16:22:08 -08:00
Leonardo de Moura
9291f59c8f chore: add changes.md 2022-01-31 15:52:28 -08:00
Sebastian Ullrich
6f28d70d50 chore: CI: fix non-release jobs on release 2022-01-31 22:59:07 +01:00
Leonardo de Moura
f02013fd76 fix: induction MetaM tactic
The major premise may be a let-declaration.

closes #983
2022-01-31 13:41:38 -08:00
Joscha
d2dcff1f9a refactor: address review comments 2022-01-31 21:36:37 +01:00
Joscha
bfc185e98e fix: don't duplicate definition and declaration requests 2022-01-31 21:36:37 +01:00
Joscha
4545e183d8 fix: go to definition in modified file 2022-01-31 21:36:37 +01:00
Joscha
ccf492b61d feat: implement partial ilean updates 2022-01-31 21:36:37 +01:00
tydeu
768e8f76ec chore: update Lake 2022-01-31 14:31:31 +01:00
Sebastian Ullrich
dfc19755cb chore: CI: fsan-blacklist laketest_ffi as well 2022-01-31 14:29:12 +01:00
Sebastian Ullrich
f3279824a3 fix: Windows: do not use standard sysroot 2022-01-30 17:43:14 +01:00
Sebastian Ullrich
f9ff9ab3fd doc: move documentation on syntax match semantics to elaborator docstring 2022-01-29 08:40:03 -08:00
Sebastian Ullrich
ce58ded16f fix: syntax match of literals
Fixes #801
2022-01-29 08:40:03 -08:00
Gabriel Ebner
7d4ae642fb fix: recursively copy subfields in diamond extends 2022-01-29 08:31:34 -08:00
Sebastian Ullrich
4d17f1ccb3 chore: CI: rename Nix job to make available to branch protection rule 2022-01-29 17:30:01 +01:00
Wojciech Nawrocki
2d1cea0864 feat: inform server if widgets are available 2022-01-29 10:04:25 +01:00
Leonardo de Moura
3db640e770 chore: avoid Name.quickLt
`Name.quickLt` uses hash code and may produce counterintuitive results
to users.
2022-01-28 09:48:50 -08:00
Leonardo de Moura
e5ef61225b fix: missing condition at lpo case 3 2022-01-28 09:47:35 -08:00
Leonardo de Moura
cb4a86ac68 fix: do not validate local eq theorems
see #973
2022-01-27 11:50:20 -08:00
Leonardo de Moura
d4d9995952 feat: reject user declared namespaces containing _root
see #490
2022-01-26 19:15:45 -08:00
Leonardo de Moura
941a6165e5 chore: cleanup 2022-01-26 18:26:23 -08:00
Leonardo de Moura
a63163e992 feat: do not try to discharge hypotheses at simp when type contains assignable metavariables
closes #973
see https://github.com/leanprover-community/mathport/issues/70
2022-01-26 17:57:52 -08:00
Leonardo de Moura
2fff4c42b7 fix: make sure irreducible constants are not unfolded when using the default reducibility setting 2022-01-26 11:55:21 -08:00
Leonardo de Moura
8db923e010 feat: generate error message for simp theorems that are equivalent to x = x
see #973
see https://github.com/leanprover-community/mathport/issues/70
2022-01-26 11:16:31 -08:00
Leonardo de Moura
36d7f2a1ea chore: remove dead code 2022-01-26 10:38:46 -08:00
Leonardo de Moura
cf3b8d4eb4 chore: cleanup
Make the code style more uniform.
We still have a lot of leftovers from the old frontend.
2022-01-26 09:18:17 -08:00
Leonardo de Moura
f0b502aca6 fix: increase the number of heartbeats at Expr.eqv
On issue #906, `simp` spends a lot of time checking the cache. This
process is time consuming and doesn't allocate memory. Before this
commit, it would take a long time to get the "maximum number of
heartbeats" error message on the example included in this issue.

Closes #906
2022-01-26 08:25:33 -08:00
Leonardo de Moura
a10e32f537 fix: check "heartbeats" at simp 2022-01-26 07:50:25 -08:00
Leonardo de Moura
15cca3000a fix: withIncRecDepth was not aborting simp
It was just making it stop simplification at the current branch.

Now, elaboration is interrupted after a few seconds in the example at
issue #906.

see #906
2022-01-26 07:48:58 -08:00
Leonardo de Moura
868e95df1b feat: add Exception.isMaxRecDepth 2022-01-26 07:38:38 -08:00
Leonardo de Moura
8896c9b06d test: add variant of Formula.count_quantifiers
see #974
2022-01-25 18:47:03 -08:00
Leonardo de Moura
98407798af fix: mkEquationsFor at Match/MatchEqs.lean
closes #974
2022-01-25 18:43:51 -08:00
Leonardo de Moura
a969014eb9 chore: add matchHEq? 2022-01-25 18:43:51 -08:00
Leonardo de Moura
9c293abb9c chore: expose heqToEq tactic 2022-01-25 18:43:51 -08:00
Leonardo de Moura
6547af988b feat: add substVars 2022-01-25 18:43:51 -08:00
Sebastian Ullrich
2f02ddeba1 fix: Nix: revise propagation of load-dynlibs 2022-01-25 23:25:52 +01:00
Sebastian Ullrich
cf1654df1f fix: Nix: precompilation against stdlib, once more 2022-01-25 23:25:52 +01:00
Sebastian Ullrich
180cc59d64 chore: update Lake to https://github.com/leanprover/lake/pull/48/files 2022-01-25 23:25:52 +01:00
Sebastian Ullrich
cfaba85199 feat: load precompiled modules in the server 2022-01-25 23:25:52 +01:00
Sebastian Ullrich
a926c6b1b2 chore: Nix: more consistent drv name 2022-01-25 23:25:52 +01:00
Sebastian Ullrich
8893ba9fa0 fix: Nix: precompilation on macOS 2022-01-25 23:25:52 +01:00
Sebastian Ullrich
9b87428555 fix: Nix: work around https://github.com/NixOS/nixpkgs/issues/148189 2022-01-25 23:25:52 +01:00
Sebastian Ullrich
23db584b8f fix: Nix: precompilation against stdlib 2022-01-25 23:25:52 +01:00
Sebastian Ullrich
b601f2ffb2 perf: Nix: use bare command for shared libs 2022-01-25 23:25:52 +01:00
Sebastian Ullrich
096250a585 feat: Nix: simple, opt-in precompilation scheme 2022-01-25 23:25:52 +01:00
Sebastian Ullrich
01987dbc8e refactor: Nix: attach object drv to module drv 2022-01-25 23:25:52 +01:00
Sebastian Ullrich
ac28f89527 fix: Nix: link package's shared library dynamically against dependencies
refactor: Nix: dynlib handling
2022-01-25 23:25:52 +01:00
Leonardo de Moura
234f70fadb chore: remove the now incorrect comment 2022-01-24 19:05:05 -08:00
Leonardo de Moura
02677cf326 fix: igore instance implicit arguments in term ordering used at simp
closes #972
2022-01-24 18:57:31 -08:00
Leonardo de Moura
d4f7899591 chore: avoid code duplication setting Simp.Config 2022-01-24 18:57:31 -08:00
Sebastian Ullrich
b20ecd02d7 chore: move out lean4-mode 2022-01-24 21:23:53 +01:00
Leonardo de Moura
722bf54929 fix: trace message with incorrect MetavarContext 2022-01-24 10:34:44 -08:00
Leonardo de Moura
7ada79bf2e fix: use an AC-compatible ordering on Expr at simp
closes #968
2022-01-22 09:42:59 -08:00
Leonardo de Moura
763a337c25 chore: helper functions 2022-01-22 09:30:57 -08:00
Leonardo de Moura
d096f59f86 chore: update stage0 2022-01-22 08:06:31 -08:00
Leonardo de Moura
0615020cf7 feat: make sure Expr.approxDepth does not overflow 2022-01-22 07:45:19 -08:00
Tom Ball
0b140ea451 doc: fix error in manual example
Co-authored-by: Tom Ball <you@example.com>
2022-01-22 10:03:32 +01:00
Sebastian Ullrich
fb57b73e1f fix: Nix: compatibility with standard build 2022-01-21 09:24:43 +01:00
Leonardo de Moura
79dec8fa7c chore: fix test 2022-01-20 17:19:29 -08:00
Leonardo de Moura
253f3aa5ec chore: update stage0 2022-01-20 17:16:50 -08:00
Leonardo de Moura
d39025e343 test: add test for issue #951 2022-01-20 17:16:06 -08:00
Leonardo de Moura
893b816f82 chore: update stage0 2022-01-20 17:11:09 -08:00
Leonardo de Moura
b0083e0dd0 feat: use elaborated type to generate instance name
closes #951
2022-01-20 17:09:55 -08:00
Leonardo de Moura
a9659afa50 chore: remove old decls 2022-01-20 15:35:19 -08:00
Leonardo de Moura
70de6dabb3 chore: update stage0 2022-01-20 15:33:45 -08:00
Leonardo de Moura
6f416147b4 chore: rename coeM and liftCoeM 2022-01-20 15:33:17 -08:00
Leonardo de Moura
0c959b6942 chore: fix tests 2022-01-20 15:25:59 -08:00
Leonardo de Moura
2192e6148b chore: remove coe, coeSort, and coeFun abbreviations
The notation `↑ e` is now expanded eagerly.

See #403
2022-01-20 15:19:06 -08:00
Leonardo de Moura
7c0a790774 chore: update stage0 2022-01-20 15:10:13 -08:00
Leonardo de Moura
3c17755730 chore: prepare to remove coe definitions
The notation `↑ e` will eagerly expand the coersion.

See #403
2022-01-20 15:07:54 -08:00
Leonardo de Moura
f9fa24435d chore: remove problematic instance hasOfNatOfCoe
See #403
See https://github.com/leanprover-community/mathport/issues/94
2022-01-20 14:47:25 -08:00
Sebastian Ullrich
f0f26728ed doc: more about initializers 2022-01-20 18:55:57 +01:00
Sebastian Ullrich
dc148003cb chore: Nix: remove annoying output 2022-01-20 18:55:57 +01:00
Sebastian Ullrich
52de670497 chore: clarify safety of compile-time code execution 2022-01-20 18:55:57 +01:00
Sebastian Ullrich
c59f7a55cf fix: initialize precompiled modules 2022-01-20 18:55:57 +01:00
Leonardo de Moura
e7dd03d5d1 chore: remove tmp dir 2022-01-20 09:54:28 -08:00
Leonardo de Moura
b1a92f5cbf feat: better Repr instances for Level.Data and Expr.Data
see #619
2022-01-20 09:45:30 -08:00
Leonardo de Moura
ff4be1e1db feat: add Repr instances for Level and Expr
closes #619

TODO: a better `Repr` instance for `Expr.Data`
2022-01-20 09:26:06 -08:00
Leonardo de Moura
d190d6dda4 fix: use default reducibility when proving equation theorems for definition
Addresses issue reported by @fpfu at #945
2022-01-20 08:23:51 -08:00
Joscha
9949f92648 refactor: base findModuleWithExt on findWithExt 2022-01-20 17:20:01 +01:00
Joscha
2423a78db4 refactor: implement suggestions 2022-01-20 17:20:01 +01:00
Sebastian Ullrich
3a926b1047 fix: use user-facing private decl name in symbol query 2022-01-20 17:20:01 +01:00
Sebastian Ullrich
53d90a71ae feat: do case-sensitive symbol query if query contains upper-case char 2022-01-20 17:20:01 +01:00
Sebastian Ullrich
1168334cca fix: Unicode symbol lookup 2022-01-20 17:20:01 +01:00
Joscha
7540889bd3 feat: implement LSP workspace symbol request 2022-01-20 17:20:01 +01:00
Sebastian Ullrich
ccf1292e07 fix: rework header/lib handling with bundled clang
* use `-nostdinc` to make sure system headers don't affect us
* include clang headers with `-isystem`, which suppresses all those warnings
* do not use default sysroot on Windows after all, since that can be a
  surprising location

Fixes #922
2022-01-20 16:05:54 +01:00
Leonardo de Moura
f5509ab867 fix: equational lemma generation for definitions using named patterns
closes #945
2022-01-19 17:45:54 -08:00
Leonardo de Moura
ef449e816f chore: improve trace messages 2022-01-19 14:29:04 -08:00
Sebastian Ullrich
bbec84bb18 chore: more output on trace.Elab.info 2022-01-19 21:40:29 +01:00
Joscha
3651ebb377 fix: don't send worker notification to client 2022-01-19 16:29:10 +01:00
Sebastian Ullrich
89e460dd1b chore: CI: push .ileans to Cachix 2022-01-19 12:35:42 +01:00
Sebastian Ullrich
312944e784 fix: hover etc. on complex declaration name 2022-01-19 12:27:03 +01:00
tydeu
8e79d88d29 feat: liftOption 2022-01-19 12:22:05 +01:00
Leonardo de Moura
873a2ba8a6 feat: unfold namedPattern applications at equation theorems 2022-01-18 15:03:20 -08:00
Leonardo de Moura
1e21815e41 fix: equality theorem generation when named patterns are used
closed #945
2022-01-18 14:37:51 -08:00
Leonardo de Moura
c816524d8d feat: add subst? 2022-01-18 14:26:14 -08:00
Leonardo de Moura
c12fa6f0e2 fix: error message
The equation theorems may fail for other reasons.
2022-01-18 14:11:54 -08:00
Leonardo de Moura
a21265281b chore: remove temporary workaround 2022-01-18 14:11:54 -08:00
Arthur Paulino
98289ed3d7 feat: provide functions to build a HashMap from a List of key-value pairs
As a motivation, programming languages that implement hash maps usually provide an interface for easy instantiation.

Closes 947
2022-01-18 22:51:00 +01:00
Leonardo de Moura
63025663fd chore: update stage0 2022-01-18 12:47:36 -08:00
Leonardo de Moura
ab5e43acaa chore: update stage0 2022-01-18 12:45:27 -08:00
Leonardo de Moura
1c1e6d79a7 feat: add equality proof for named patterns
The user can optionally name the equality proof.
The new test demostrates how to name the equality proof.

closes #501
2022-01-18 12:43:01 -08:00
Leonardo de Moura
42fe01a3eb feat: add new flag to caseValues 2022-01-18 12:15:29 -08:00
Leonardo de Moura
8058bc894c feat: add AssocList.toList 2022-01-18 11:44:43 -08:00
Leonardo de Moura
cd903bde77 refactor: [s : Setoid α] => {s : Setoid α} or (s : Setoid α)
See comment at https://github.com/leanprover/lean4/issues/952#issuecomment-1015265136

cc @gebner
2022-01-18 09:24:06 -08:00
Leonardo de Moura
9d05023325 chore: remove some [specialize] annotations 2022-01-18 09:24:06 -08:00
Sebastian Ullrich
3abb70dbb5 refactor: factor out common source search path logic 2022-01-18 18:22:50 +01:00
Leonardo de Moura
b266961068 chore: fix test 2022-01-17 17:24:09 -08:00
Leonardo de Moura
4ac019ccf0 chore: update stage0 2022-01-17 17:22:02 -08:00
Leonardo de Moura
874aadd7e3 chore: update namedPattern signature
Remark: It is not being used yet.
2022-01-17 17:21:18 -08:00
Leonardo de Moura
35d25dfaaf chore: update stage0 2022-01-17 17:18:49 -08:00
Leonardo de Moura
6631f1d5b3 chore: use namedPatternOld 2022-01-17 17:18:03 -08:00
Leonardo de Moura
db9bb8dd1b chore: update stage0 2022-01-17 17:14:46 -08:00
Leonardo de Moura
0f217eb4c1 chore: prepare to change namedPattern signature 2022-01-17 17:13:09 -08:00
Leonardo de Moura
2a17233f1c chore: fix test 2022-01-17 17:07:08 -08:00
Leonardo de Moura
2c0da66ff2 chore: update stage0 2022-01-17 17:04:44 -08:00
Leonardo de Moura
be4c86f780 chore: remove temporary workarounds 2022-01-17 17:03:15 -08:00
Leonardo de Moura
05b9240c72 chore: update stage0 2022-01-17 16:59:20 -08:00
Leonardo de Moura
f8653a8cb7 chore: add temporary workaround 2022-01-17 16:58:39 -08:00
Leonardo de Moura
b142f709e1 chore: update stage0 2022-01-17 16:55:31 -08:00
Leonardo de Moura
2c690926cf feat: update namedPattern parser 2022-01-17 16:49:20 -08:00
Leonardo de Moura
de11f7e1bc feat: add sizeOf spec lemmas as simp theorems 2022-01-17 16:14:38 -08:00
Leonardo de Moura
8f47043aee chore: add trace message for sizeOf theorem 2022-01-17 15:42:42 -08:00
Gabriel Ebner
ab276a5ae3 chore: show declaration with sorry in #eval 2022-01-17 13:18:22 -08:00
Leonardo de Moura
03a5c5034f chore: update stage0 2022-01-17 13:10:09 -08:00
Leonardo de Moura
a272b222f1 chore: update stage0 2022-01-17 13:08:00 -08:00
Leonardo de Moura
999e125e3f feat: mark arguments such as {_ : BEq α} as specialization target
We want to specialize functions such as
```
def find? {_ : BEq α} {_ : Hashable α} : PersistentHashMap α β → α → Option β
  | { root := n, .. }, k => findAux n (hash k |>.toUSize) k
```
2022-01-17 13:05:50 -08:00
Gabriel Ebner
561a869e49 fix: provide reference implementation for Array.modify 2022-01-17 12:41:12 -08:00
Leonardo de Moura
dd3d8f6fad feat: complete namespaces
closes #940
2022-01-17 10:03:36 -08:00
Leonardo de Moura
da06bb6605 fix: matching inside new termination_by 2022-01-17 08:47:05 -08:00
Leonardo de Moura
98af42077c chore: fix doc 2022-01-16 09:28:03 -08:00
Leonardo de Moura
189f4bd372 chore: fix tests 2022-01-15 12:18:09 -08:00
Leonardo de Moura
bac91b9b5b chore: remove arbitrary 2022-01-15 12:14:27 -08:00
Leonardo de Moura
20d5b5b9c0 chore: update stage0 2022-01-15 12:03:17 -08:00
Leonardo de Moura
579908e9b1 chore: using Inhabited.default at Deriving/Inhabited 2022-01-15 11:59:43 -08:00
Leonardo de Moura
7d5f14b4a7 chore: elaborate default_or_ofNonempty% and add mkDefault 2022-01-15 11:55:58 -08:00
Leonardo de Moura
5c69d63157 chore: update stage0 2022-01-15 11:52:40 -08:00
Leonardo de Moura
9de58c66eb chore: add default_or_ofNonempty% 2022-01-15 11:50:39 -08:00
Leonardo de Moura
a3a134a297 chore: export Inhabited.default 2022-01-15 11:50:28 -08:00
Leonardo de Moura
c1fccf19cb chore: fix test 2022-01-15 11:46:11 -08:00
Leonardo de Moura
901c0dba83 chore: update lake 2022-01-15 11:44:40 -08:00
Leonardo de Moura
b0d9c16c7a chore: rename PointedType => NonemptyType 2022-01-15 11:43:53 -08:00
Henrik Böving
c1b31a57eb feat: store ModuleData of imported modules in EnvironmentHeader 2022-01-15 10:40:52 -08:00
tydeu
07bfdc02e7 chore: update Lake 2022-01-15 17:57:51 +01:00
Leonardo de Moura
5e462f704a chore: update stage0 2022-01-14 20:43:22 -08:00
Leonardo de Moura
83b616ad07 chore: update lake 2022-01-14 20:42:36 -08:00
Leonardo de Moura
e3241e82bc feat: define PointedType as { α : Type u // Nonempty α } 2022-01-14 20:36:51 -08:00
Leonardo de Moura
23e27f657f chore: update stage0 2022-01-14 20:29:26 -08:00
Leonardo de Moura
6ea0aaf35a fix: do not invoke add_extern for declarations marked with implementedBy 2022-01-14 20:27:50 -08:00
Leonardo de Moura
9499cea2a5 fix: bug at skip_code_generation 2022-01-14 19:58:24 -08:00
Leonardo de Moura
42db1f09d2 chore: update lake 2022-01-14 19:49:30 -08:00
Leonardo de Moura
b970919978 chore: remove unnecessary Inhabited 2022-01-14 19:48:10 -08:00
Leonardo de Moura
acd482c5f2 feat: define Array.modify without using Inhabited 2022-01-14 19:47:42 -08:00
Leonardo de Moura
9c5668515c chore: update stage0 2022-01-14 19:21:29 -08:00
Leonardo de Moura
b22a3a4cc4 feat: skip code generation for declarations marked with implementedBy, init, and builtinInit
This is a bit hackish. We should clean up when we rewrite the compiler
in Lean.
2022-01-14 19:20:16 -08:00
Leonardo de Moura
a438a2ee21 feat: elaborate arbitrary_or_ofNonempty% and use it to define constants 2022-01-14 17:22:39 -08:00
Leonardo de Moura
2fe59456fd chore: update stage0 2022-01-14 17:19:34 -08:00
Leonardo de Moura
0a726a755f feat: add helper parser arbitrary_or_ofNonempty% 2022-01-14 17:11:55 -08:00
Leonardo de Moura
226d828e19 chore: update stage0 2022-01-14 16:51:05 -08:00
Leonardo de Moura
c34adb7dd5 feat: allow partial definitions to be define if type is non empty 2022-01-14 16:50:36 -08:00
Leonardo de Moura
f1adedb2de feat: add Classical.ofNonempty 2022-01-14 15:59:11 -08:00
Leonardo de Moura
83b69bc340 refactor: move Classical.choice and Nonempty to Prelude 2022-01-14 15:59:11 -08:00
Sebastian Ullrich
9ab5f0376e feat: Nix: iTree attribute for symlinking (complete) ilean files 2022-01-14 19:02:10 +01:00
Sebastian Ullrich
753e396705 fix: recurse in findAllWithExt 2022-01-14 18:59:58 +01:00
Sebastian Ullrich
6ec406b7d0 feat: System.FilePath.walkDir 2022-01-14 16:22:14 +01:00
larsk21
b712918db9 fix: unify handleDefinition for imports 2022-01-14 10:32:06 +01:00
larsk21
ecaa004dcc feat: make withWaitFindSnap consider all snaps of a document 2022-01-14 10:32:06 +01:00
larsk21
e584560b17 feat: enable "go to definition" for imports 2022-01-14 10:32:06 +01:00
larsk21
89bbaf514e feat: include imports in header snap info tree 2022-01-14 10:32:06 +01:00
Joscha
6d809e7cd1 test: remove references test
This test no longer works since the 'references' request now requires at
least a watchdog, but this kind of test only work with file workers.
2022-01-14 09:18:57 +01:00
Sebastian Ullrich
8e5fc66330 fix: do not error on non-existent search path entries 2022-01-14 09:18:57 +01:00
Sebastian Ullrich
a0e8c6183b fix: parser should create choice node even on error 2022-01-14 09:18:57 +01:00
Joscha
8c5868e106 perf: reduce size of ilean files 2022-01-14 09:18:57 +01:00
Sebastian Ullrich
37f5be1b26 chore: fix servertest_init_exit 2022-01-14 09:18:57 +01:00
Sebastian Ullrich
d503fe6d13 refactor: avoid double exception layer with AsyncList 2022-01-14 09:18:57 +01:00
Joscha
d8ec900ae9 refactor: use array instead of list in AsyncElabState 2022-01-14 09:18:57 +01:00
Joscha
ab52480b69 fix: implement suggestions 2022-01-14 09:18:57 +01:00
Joscha
4bcf7ab31f style: add copyright headers 2022-01-14 09:18:57 +01:00
Joscha
b9f8f5eb38 fix: find references of function parameters 2022-01-14 09:18:57 +01:00
Joscha
281ede6ed4 feat: handle references notifications 2022-01-14 09:18:57 +01:00
Joscha
f98cf0289c feat: send references notification when file evaluation finishes 2022-01-14 09:18:57 +01:00
Joscha
7cce91acb4 refactor: move some reference-related types to Lean.Data
These types are required for worker->watchdog notifications.
2022-01-14 09:18:57 +01:00
Joscha
088433dc57 refactor: let AsyncList creation be stateful 2022-01-14 09:18:57 +01:00
Joscha
67aa823ae2 fix: resolve symlinks for the LSP client 2022-01-14 09:18:57 +01:00
Joscha
bce56fdc0c feat: implement reference request 2022-01-14 09:18:57 +01:00
Joscha
7abdf94fc5 feat: respond to reference request in watchdog 2022-01-14 09:18:57 +01:00
Joscha
4fd1d22c31 feat: load and unload ileans on LSP notifications 2022-01-14 09:18:57 +01:00
Joscha
4e12cc902b feat: load ilean files from olean search path 2022-01-14 09:18:57 +01:00
Joscha
567a854a15 feat: load search path for source files in watchdog 2022-01-14 09:18:57 +01:00
Joscha
87b8afff6b feat: register file watcher for .ilean files 2022-01-14 09:18:57 +01:00
Joscha
bcc499b7c0 feat: build .ilean files next to .olean files 2022-01-14 09:18:57 +01:00
Joscha
346b50a22e chore: update stage0 2022-01-14 09:18:57 +01:00
Joscha
3f998c68bc feat: export reference info to ilean files 2022-01-14 09:18:57 +01:00
Joscha
96ed620933 feat: collect reference info from InfoTrees 2022-01-14 09:18:57 +01:00
Joscha
efb964956e feat: add FileRefMap and convert to/from JSON 2022-01-14 09:18:57 +01:00
Joscha
fead5526bc feat: add -i cli option 2022-01-14 09:18:57 +01:00
Simon Hudon
ec3cc0cc45 feat: lean-mode: auto-select lean 3 mode 2022-01-14 09:17:34 +01:00
Leonardo de Moura
6d235586f0 fix: ignore TC failures while processing patterns
closes #948
2022-01-13 10:55:09 -08:00
Leonardo de Moura
1620987b6c fix: recursive applications in discriminants 2022-01-13 09:56:33 -08:00
Sebastian Ullrich
b56fa81b70 chore: CI: sanitizer-blacklist Lake test again
Apparently 1500s are not sufficient for termination...
2022-01-13 17:10:07 +01:00
Leonardo de Moura
8c45c844aa test: add wellfounded test 2022-01-12 17:16:43 -08:00
Leonardo de Moura
3fbf5acbee fix: add missing [reducible] annotations Init/WF.lean 2022-01-12 17:12:55 -08:00
Leonardo de Moura
98864f707e test: add test for #879
The new `termination_by` syntax should address issue #879

closes #879
2022-01-12 16:25:09 -08:00
Leonardo de Moura
7fe6881c42 feat: use new termination_by syntax 2022-01-12 16:23:25 -08:00
Leonardo de Moura
35a49ca535 chore: update stage0 2022-01-12 16:23:25 -08:00
Leonardo de Moura
9162901c86 fix: expandTerminationByNonCore 2022-01-12 16:22:54 -08:00
Leonardo de Moura
91a0ac8a12 feat: elaborate new termination_by syntax 2022-01-12 16:15:30 -08:00
Leonardo de Moura
49b2860f2a feat: add Meta.rename tactic 2022-01-12 16:15:30 -08:00
Leonardo de Moura
addcbc6fa3 feat: process termination_by syntax 2022-01-12 16:15:30 -08:00
Simon Hudon
6820c8bd92 feat: create lsp workspaces automatically 2022-01-12 19:26:55 +01:00
Leonardo de Moura
111d09fda3 fix: must apply afterCompilation attributes *after* smart unfolding definition was declared
The `[simp]` attribute checks whether the smart unfolding defintion
has been declared.

closes #946
2022-01-12 08:28:03 -08:00
Leonardo de Moura
45bd328d5e fix: tests and add WellFoundedRelation.rel to list of definitions to unfold at decreasing_tactic 2022-01-12 08:28:03 -08:00
Leonardo de Moura
e7eab602d9 fix: missing consumeAutoOptParam at addNewArg 2022-01-12 08:28:03 -08:00
Leonardo de Moura
7a86b613dc chore: remove old comment 2022-01-12 08:28:03 -08:00
Leonardo de Moura
a1ab5c0ccb feat: simplify termination_by new syntax
We don't need `using` anymore since we are going to use TC inference.
2022-01-12 08:28:03 -08:00
Leonardo de Moura
1a6abe1dad feat: WellFoundedRelation as a class 2022-01-12 08:28:03 -08:00
Gabriel Ebner
50abc3e295 fix: correctly pretty-print @Eq 2022-01-12 09:41:41 +01:00
Gabriel Ebner
bdc80ce50d fix: potential nontermination in delabFor 2022-01-12 09:41:41 +01:00
Gabriel Ebner
9132b27e80 fix: delabAppImplicit: strip mdata from function 2022-01-12 09:41:41 +01:00
Sebastian Ullrich
bcf61cc7bb chore: CI: remove ctest timeout, for now
Hopefully lsan will now have sufficient time to actually terminate
2022-01-12 10:24:45 +01:00
Leonardo de Moura
de19767594 feat: basic skeleton for termination_by' vs termination_by 2022-01-11 16:53:39 -08:00
Leonardo de Moura
4e5a51aa24 chore: fix test 2022-01-11 16:23:26 -08:00
Leonardo de Moura
868a43a747 chore: remove dead code 2022-01-11 16:22:20 -08:00
Leonardo de Moura
f9b79092f6 feat: new termination_by syntax 2022-01-11 15:36:50 -08:00
Leonardo de Moura
068cc700d8 test: ackermann 2022-01-11 15:03:07 -08:00
Leonardo de Moura
381f66428a chore: use termination_by'
We are going to define a higher level syntax for `termination_by`.
2022-01-11 15:00:53 -08:00
Leonardo de Moura
0434c36f89 chore: remove old version 2022-01-11 14:50:15 -08:00
Leonardo de Moura
4e47ef0cbb chore: update stage0 2022-01-11 14:48:42 -08:00
Leonardo de Moura
430b641e81 feat: use decreasing_tactic 2022-01-11 14:47:19 -08:00
Leonardo de Moura
74f732f4cb chore: update stage0 2022-01-11 14:45:16 -08:00
Leonardo de Moura
ce76ad44ea feat: add terminationByCore parser 2022-01-11 14:44:36 -08:00
Leonardo de Moura
ca89da28d0 chore: prepare to rename default_decreasing_tactic 2022-01-11 14:42:25 -08:00
Leonardo de Moura
2464da0dca feat: add support for PSigma.Lex at default_decreasing_tactic 2022-01-11 14:41:28 -08:00
Leonardo de Moura
a087b21bc0 fix: bug at WF/Fix.lean 2022-01-11 14:38:31 -08:00
Leonardo de Moura
ec49c31337 chore: make sure PSigma.lex signature is similar to Prod.lex 2022-01-11 14:37:53 -08:00
Leonardo de Moura
d953ac8d0d feat: allow users to use initialize registerBuiltinDerivingHandler ... 2022-01-11 09:50:09 -08:00
Leonardo de Moura
93f3773d83 chore: cleanup 2022-01-10 16:25:07 -08:00
Leonardo de Moura
dae3489fe2 feat: remove partials from Init/Data/Array/Basic.lean 2022-01-10 16:05:33 -08:00
Leonardo de Moura
a02421185c fix: add support for BinderInfo.auxDecl at delabLam 2022-01-10 15:18:49 -08:00
Leonardo de Moura
cee8ad1b66 chore: fix codebase 2022-01-10 15:07:55 -08:00
Leonardo de Moura
762b0f42ba chore: fix tests 2022-01-10 15:06:03 -08:00
Leonardo de Moura
a28ff92010 chore: update stage0 2022-01-10 15:05:47 -08:00
Leonardo de Moura
4c918a2363 feat: use default_decreasing_tactic at WF/Fix.lean 2022-01-10 14:55:38 -08:00
Leonardo de Moura
739ef7d166 fix: annotate let rec declarations as auxDecl
Reason:
1- Tactics such as `assumption` should ignore them.
2- We must annotate recursive applications with `mkRecAppWithSyntax`.
2022-01-10 14:35:05 -08:00
Leonardo de Moura
57b8912279 chore: fix tests 2022-01-10 14:33:02 -08:00
Leonardo de Moura
0dd3ce0598 chore: fix test 2022-01-10 14:31:23 -08:00
Leonardo de Moura
7789779020 feat: add simple default tactic for well-founded recursion 2022-01-10 14:26:08 -08:00
Leonardo de Moura
16b4aa81e5 chore: add helper lemmas for well-founded recursion 2022-01-10 14:07:35 -08:00
Leonardo de Moura
241db0fed6 chore: fix name 2022-01-10 13:20:49 -08:00
Leonardo de Moura
929aafa4c8 fix: generate an error if declaration name clashes with variable name
closes #799
2022-01-10 12:08:11 -08:00
Josh Levine
99f6469761 doc: fix typo (#935) 2022-01-10 10:26:24 -08:00
Sebastian Ullrich
bcd7185f42 chore: CI: try reenabling sanitized Lake test 2022-01-10 18:35:22 +01:00
Sebastian Ullrich
768df1581c chore: CI: put llvm-symbolizer in PATH for asan/lsan backtraces 2022-01-10 18:35:22 +01:00
Sebastian Ullrich
3acc21e128 chore: CI: try to make lsan terminate 2022-01-10 18:35:22 +01:00
Gabriel Ebner
dc65bb080a fix: race condition in RPC request handler 2022-01-10 13:37:40 +01:00
Sebastian Ullrich
60a70372af chore: remove stray file breaking stage 0 update
/cc @leodemoura
2022-01-10 12:57:51 +01:00
Josh Levine
1637d75d3f doc: fix trivial typo 2022-01-09 10:19:26 +01:00
Leonardo de Moura
b2d26380f2 fix: remove auxiliary discriminant let-declarations 2022-01-07 15:03:19 -08:00
Leonardo de Moura
1cf8467847 feat: add unfold conv tactic 2022-01-07 13:51:45 -08:00
Leonardo de Moura
49d0f3af52 test: unfold tactic 2022-01-07 13:51:45 -08:00
Leonardo de Moura
57b9e0852e fix: clear local context at mkUnfoldEq 2022-01-07 13:51:45 -08:00
Leonardo de Moura
b50e82bc93 feat: unfold tactic 2022-01-07 13:51:45 -08:00
Leonardo de Moura
c303bf6916 refactor: add helper methods for simp 2022-01-07 13:51:45 -08:00
Leonardo de Moura
b1b4705c14 feat: add unfold tactic parsers 2022-01-07 13:51:45 -08:00
Leonardo de Moura
e8a4dbbc2a chore: document and cleanup mkUnfoldProof 2022-01-07 13:51:45 -08:00
Leonardo de Moura
b797c982fc feat: add mkUnfoldProof 2022-01-07 13:51:45 -08:00
Gabriel Ebner
f146d456ce fix: only enable InsertReplaceEdit if supported 2022-01-07 20:28:10 +01:00
larsk21
8c2d7a35d3 fix: make set_option completion replace typed partial name 2022-01-07 17:06:26 +01:00
Mario Carneiro
dcaf3c615f fix: induction generalizing precedence 2022-01-07 10:45:45 +01:00
Leonardo de Moura
cc4c82a6e7 chore: update stage0 2022-01-06 17:44:42 -08:00
Leonardo de Moura
98f4e51a12 feat: add mkUnfoldEq skeleton 2022-01-06 17:42:45 -08:00
Leonardo de Moura
bef161caf7 feat: add better support for discharging equation theorem hypotheses 2022-01-06 14:42:23 -08:00
Andrei Cheremskoy
5eea97534f chore(doc): remove duplicate Tactics section (#927) 2022-01-06 14:03:15 -08:00
Leonardo de Moura
df6095e580 fix: casesOnStuckLHS method
It was not general enough.
2022-01-06 13:54:17 -08:00
Leonardo de Moura
90b179bea9 fix: add equation theorems even if definition supports smart unfolding
See new test.
2022-01-06 13:53:03 -08:00
Leonardo de Moura
d8d7d63830 fix: registers eqns info before adding definition
Otherwise `[simp]` at definition will fail to generate equational theorems.
2022-01-06 12:24:40 -08:00
Leonardo de Moura
7acbbb4fbb fix: auxiliary whnfAux used at mkEqns 2022-01-06 09:57:41 -08:00
Leonardo de Moura
60934bf1d5 feat: add support for removing [simp] attribute from definitions with equational theorems 2022-01-05 16:57:59 -08:00
Leonardo de Moura
c2e52bd577 feat: use getEqnsFor? when applying [simp] at definitions 2022-01-05 15:59:39 -08:00
Leonardo de Moura
ff49fd6b7e fix: apply afterCompilation attributes after we have compiled *all* definitions in a mutual block 2022-01-05 15:57:51 -08:00
Leonardo de Moura
030e932db8 feat: use getEqnsFor? at simp 2022-01-05 11:28:24 -08:00
Leonardo de Moura
4d1343d670 chore: use _eq instead of eq to name auto generated equational theorems 2022-01-04 17:23:34 -08:00
Leonardo de Moura
b2918e0c76 test: add tests for WF.mkEqns 2022-01-04 17:18:51 -08:00
Leonardo de Moura
d782a97f5c feat: add WF.mkProof for WF.mkEqns 2022-01-04 17:00:54 -08:00
Leonardo de Moura
2a0cd18d4b feat: add WF.mkEqns 2022-01-04 15:44:05 -08:00
Leonardo de Moura
fa597c6fb8 chore: update stage0 2022-01-04 15:32:33 -08:00
Leonardo de Moura
d941e97716 feat: add WF/Eqns.lean skeleton 2022-01-04 15:31:22 -08:00
Leonardo de Moura
947240ef9e refactor: add PreDefinition/Eqns.lean 2022-01-04 13:52:41 -08:00
ammkrn
f2cc9080a3 doc: document the split tactic 2022-01-04 13:28:36 -08:00
Mario Carneiro
5a7c9f2d35 chore: add showRhs definition 2022-01-04 09:28:29 -08:00
Leonardo de Moura
62d03fe8ad chore: update stage0 2022-01-04 09:27:33 -08:00
Mario Carneiro
9ee0d08cb5 chore: add doc 2022-01-04 09:26:34 -08:00
Mario Carneiro
3716e9a2ed chore: use a different syntax kind for suffices-by
chore: update src/Lean/Parser/Term.lean

Co-authored-by: Gabriel Ebner <gebner@gebner.org>
2022-01-04 09:26:32 -08:00
Gabriel Ebner
83e167dfb5 feat: append filename to worker command-line
This change has no effect on the server behavior.  The only difference
is that the filename now shows up in `htop`, `ps`, etc., which makes it much
easier to see what Lean processes are running, and which are using 100%
CPU, etc.
2022-01-04 15:10:46 +01:00
Sebastian Ullrich
64971a1e3c fix: term macro errors should be fatal 2022-01-04 11:20:18 +01:00
Leonardo de Moura
a000ee4249 chore: update stage0 2022-01-03 10:33:37 -08:00
Leonardo de Moura
b9f7d1defb fix: constant folding after erasure
closes #909
2022-01-03 10:33:07 -08:00
Leonardo de Moura
0e479d1f9f chore: use double ticks 2022-01-03 10:30:05 -08:00
Leonardo de Moura
bf17eec439 chore: update stage0 2022-01-03 09:37:18 -08:00
Leonardo de Moura
e9c112007b fix: avoid Syntax trees leaks into .olean files
closes #918
2022-01-03 09:36:06 -08:00
Leonardo de Moura
52b6a04088 test: for #916 2022-01-03 07:57:16 -08:00
Mario Carneiro
5e36162f9b fix: adapt to doHave syntax change 2022-01-03 07:55:52 -08:00
Mario Carneiro
3253231d59 feat: make rw [] syntactically correct 2022-01-03 07:23:24 -08:00
Leonardo de Moura
7dcc026cd1 chore: update stage0 2022-01-03 07:16:13 -08:00
Gabriel Ebner
bc5bd5a671 feat: allow the compiler to optimize unsafeCast 2022-01-03 07:13:55 -08:00
Gabriel Ebner
5cdaeac36f chore: update stage0 2022-01-03 07:13:55 -08:00
Gabriel Ebner
e605c541d0 fix: do not infer type in erase_irrelevant
At the time erase_irrelevant is called, we have already eliminated the
`cast`-applications.  Therefore non-atomic expressions may no longer
be well-typed (and `infer_type` can fail).
2022-01-03 07:13:55 -08:00
gabriel-doriath-dohler
6986032b38 doc: correct the link to "Lean Together 2021: Metaprogramming in Lean 4 continued" 2022-01-03 07:06:04 -08:00
Sebastian Ullrich
bbfcb1cfb2 perf: allocation-free for i in [n:m] do 2022-01-03 07:03:56 -08:00
Sebastian Ullrich
555584375a fix: compare fields top-down in deriving Ord 2022-01-03 07:02:13 -08:00
Sebastian Ullrich
132898f7e7 fix: reinstate monadic panic workaround 2022-01-03 14:58:24 +01:00
Henrik Böving
2d85c9ba2f chore: fix notation test
The ppNotationCode.lean test failed because the output of the notation
elaborator changed (purposely), adapt it to the new output.
2022-01-03 13:47:11 +01:00
Sebastian Ullrich
75233a40f7 chore: update stage0 2022-01-03 13:46:56 +01:00
Henrik Böving
4ee058039b chore: apply suggestions from code review
Co-authored-by: Gabriel Ebner <gebner@gebner.org>
2022-01-03 13:43:33 +01:00
Henrik Böving
5d3e3b9296 fix: don't drop tags in identNoAntiquot 2022-01-03 13:43:33 +01:00
Henrik Böving
6fe010d0c2 fix: keep info in auto generated notation delaborators
Previously automatically generated delaborators for syntax declared with
the notation (and derived) keywords would silently drop information
during delaboration.
2022-01-03 13:43:33 +01:00
Henrik Böving
cbedff5aba feat: optionally add information to all symbols during delaboration
Add an option called pp.tagSymbols which, if set, makes the
delaborator add term information to all symbols it can during
delaboration. This option is disabled per default because it would
break the LSP server's hovering behaviour. It is however useful
when for example automatically generating interactive documentation.
2022-01-03 13:43:33 +01:00
Mac
748c9ab73a chore: tweak error message
Co-authored-by: Wojciech Nawrocki <wjnawrocki+gh@protonmail.com>
2021-12-27 09:44:11 +01:00
tydeu
30bdd4e751 doc: add docstring for chainLspRequestHandler 2021-12-27 09:44:11 +01:00
tydeu
004e172f5d feat: LSP request handler chaining 2021-12-27 09:44:11 +01:00
Sebastian Ullrich
3da76efa10 chore: Nix: remove Leanpkg from default deps 2021-12-25 17:00:20 +01:00
Gabriel Ebner
70ef4e529c feat: allow attributes on structures and inductives 2021-12-23 08:04:36 -08:00
Gabriel Ebner
f43f74e78f chore: suppress newline after . 2021-12-23 13:56:22 +01:00
Gabriel Ebner
72851652f1 fix: spacing in suffices...by 2021-12-23 13:56:22 +01:00
Gabriel Ebner
25714a8ee1 fix: calc syntax roundtrip 2021-12-23 13:56:22 +01:00
Mario Carneiro
7956a9bb15 chore: typos 2021-12-23 10:14:39 +01:00
Sebastian Ullrich
292fb257a7 perf: do not specialize Prop typeclasses 2021-12-22 17:48:11 -08:00
Sebastian Ullrich
399ad64854 perf: do not specialize Inhabited 2021-12-22 17:48:11 -08:00
Sebastian Ullrich
45e8d9af43 feat: support [nospecialize] on typeclasses 2021-12-22 17:48:11 -08:00
Sebastian Ullrich
b4385bd259 perf: export lake symbols for the interpreter 2021-12-22 23:33:58 +01:00
Gabriel Ebner
546bb8f053 fix: widgets: do not highlight entire expression in popup 2021-12-21 21:54:51 +01:00
Sebastian Ullrich
fdd939fc40 fix: accidental memory leak in last commit 2021-12-21 19:43:02 +01:00
Sebastian Ullrich
3318f1fb05 feat: record declaration name in interpretation profile 2021-12-21 19:04:58 +01:00
Sebastian Ullrich
c62c8bd64b chore: reenable servertest_edit 2021-12-21 18:11:28 +01:00
Gabriel Ebner
412691c958 feat: support LEAN_NUM_THREADS environment variable 2021-12-21 17:01:08 +01:00
Sebastian Ullrich
5b653197db chore: use --run for servertests
/cc @Garmelon
2021-12-21 16:04:21 +01:00
Sebastian Ullrich
cbdad10419 chore: exclude flaky laketest under sanitizer for now
unclear how to reproduce
2021-12-21 12:19:22 +01:00
Sebastian Ullrich
b732484663 fix: do not consider worker threads as idle during startup
Without this change, enqueuing multiple tasks before the first worker
was started led to only a single worker being created. Now the first
increment and decrement happen under the task manager mutex, so
effectively the worker is never idle until it is out of tasks.
2021-12-21 12:01:23 +01:00
Leonardo de Moura
b278a20ac2 feat: ensure #eval converts unassigned universe metavars into parameters
see #898
2021-12-20 06:11:36 -08:00
Sebastian Ullrich
51dc32957b feat: show universe args on hover
We might also want to replace them with fresh vars to make the hover
completely independent of the context, but this change at least avoids
any hidden information.
2021-12-20 10:51:44 +01:00
Sebastian Ullrich
068ea1beb4 fix: leanc: do not change sysroot
Apparently clang is smart enough to look up runtime files missing from
the sysroot in the installation directory automatically.
2021-12-19 18:55:57 +01:00
Chris Lovett
c3a9860dc8 doc: replace leanpkg info with info about Lake
Fixes #789
2021-12-19 17:23:25 +01:00
Sebastian Ullrich
6f9c6e4556 doc: match: mention (generalizing := true) 2021-12-19 11:14:27 +01:00
Sebastian Ullrich
5f96a9fc4d fix: do not show type of sort in hover
Fixes #896
2021-12-19 11:03:15 +01:00
tydeu
f4a73889e7 feat: expose more version info (e..g., toolchain) 2021-12-19 10:44:35 +01:00
Leonardo de Moura
92a511be29 chore: fix test 2021-12-18 11:05:37 -08:00
Leonardo de Moura
6499798a35 chore: update stage0 2021-12-18 11:01:54 -08:00
Sebastian Ullrich
167dccce0b chore: move Leanpkg.leanVersionString to Init 2021-12-18 10:59:37 -08:00
Sebastian Ullrich
234d806f6b chore: deprecate leanpkg 2021-12-18 10:59:37 -08:00
Mario Carneiro
f17064809c fix doctest 2021-12-18 10:58:57 -08:00
Mario Carneiro
f22f699d62 feat: split replicate / replicateTR with @[csimp] 2021-12-18 10:58:57 -08:00
Leonardo de Moura
be6bc67eb0 fix: ensure match-expressions compiled using if-then-else can be reduced with TransparencyMode.reducible
closes #891
2021-12-18 10:55:42 -08:00
Leonardo de Moura
b3d8766b09 chore: use doubleticks at WHNF.lean 2021-12-18 08:43:50 -08:00
Leonardo de Moura
b6fbdd8679 feat: add Meta.Context.canUnfold? 2021-12-18 08:25:56 -08:00
Leonardo de Moura
c954fc9ec7 fix: bug at simpLoop 2021-12-18 06:48:08 -08:00
Sebastian Ullrich
cd94ec20b0 fix: aux_def: avoid creating unparseable names 2021-12-17 14:21:35 -08:00
Mario Carneiro
51a78fd7af fix: change argument order of List.get[!?D] 2021-12-17 14:21:00 -08:00
Mario Carneiro
caf09e85ad chore: universe generalize implies_true 2021-12-17 14:19:54 -08:00
Leonardo de Moura
d51def739e chore: update stage0 2021-12-17 07:25:59 -08:00
Leonardo de Moura
dce55f79ed feat: eliminate recursive application syntax annotation at addAndCompileUnsafe 2021-12-17 07:24:44 -08:00
Leonardo de Moura
7df9cf6a0a feat: eliminate "recAppSyntax" information during structural recursion 2021-12-17 07:15:14 -08:00
Leonardo de Moura
6b82e15069 feat: preserve variable names when packing domain 2021-12-17 07:10:26 -08:00
Leonardo de Moura
8b7411bdd8 feat: improve error location at well-founded recursion 2021-12-17 06:50:20 -08:00
Sebastian Ullrich
9e5ff3db0e feat: setMainModule in worker 2021-12-17 12:22:53 +01:00
Sebastian Ullrich
ca740f5687 chore: fix copy-produced 2021-12-17 12:22:53 +01:00
Sebastian Ullrich
51adfa2e0c fix: do not call lake print-paths for lakefile.lean
Fixes #873
2021-12-17 12:22:30 +01:00
tydeu
e34c892f89 chore: update Lake 2021-12-17 10:20:37 +01:00
Sebastian Ullrich
5a16745ad9 chore: Nix: add devShell 2021-12-17 09:43:22 +01:00
Leonardo de Moura
2d4d5ae96f feat: save syntax around recursive applications
Motivation: better error messages at structural and well-founded recursion.
2021-12-16 17:13:55 -08:00
Leonardo de Moura
e38fab1b4e fix: ignore Expr.MData at deltaRHS? 2021-12-16 16:58:10 -08:00
Leonardo de Moura
de29657594 feat: implement bool operator==(data_value const & a, data_value const & b) using Lean autogenerated code 2021-12-16 16:37:47 -08:00
Leonardo de Moura
dbe96a4434 chore: update stage0 2021-12-16 15:48:29 -08:00
Leonardo de Moura
867134614b feat: add constructor DataValue.ofSyntax 2021-12-16 15:41:29 -08:00
Gabriel Ebner
e65f3fe810 fix: use redirected stderr for tout() 2021-12-16 10:23:05 -08:00
Sebastian Ullrich
1221bdd3c7 fix: use redirected stderr for timeit & allocprof 2021-12-16 06:38:35 -08:00
Sebastian Ullrich
87e860f871 perf: Array.push: move elements directly when source is unique 2021-12-16 06:37:37 -08:00
tydeu
72cfe18e9f chore: update Lake 2021-12-16 11:10:33 +01:00
Joe Hendrix
5a307a93ac fix: bug at ByteArray.copySlice 2021-12-16 11:05:19 +01:00
Leonardo de Moura
fa8b015603 chore: update stage0 2021-12-15 17:09:39 -08:00
Leonardo de Moura
81f7335269 fix: ensure motive is type correct at simpProj 2021-12-15 17:07:31 -08:00
Leonardo de Moura
0a81093db5 fix: bug at simpProj
This bug was reported at https://github.com/dwrensha/lean4-maze/issues/1
2021-12-15 17:07:00 -08:00
Leonardo de Moura
9a24db4e86 fix: check generated motives at notation
This commit also improves the `▸` notation a bit.
It now tries `subst` (if applicable) before failing.
2021-12-15 16:16:42 -08:00
Leonardo de Moura
89edc184fb feat: compleation at #print command 2021-12-15 13:13:39 -08:00
Leonardo de Moura
653b684651 feat: improve getCompletionKindForDecl 2021-12-15 12:57:09 -08:00
Leonardo de Moura
7d7c6d8be5 feat: add CompletionItemKind 2021-12-15 11:24:11 -08:00
Leonardo de Moura
31f845c5ed feat: keyword completion 2021-12-15 11:24:11 -08:00
Leonardo de Moura
043e9c80b4 feat: add Trie.findPrefix 2021-12-15 11:24:11 -08:00
Sebastian Ullrich
ba83721109 chore: add comment for previous fix 2021-12-15 20:10:48 +01:00
Sebastian Ullrich
35e623fca0 chore: update stage0 2021-12-15 15:58:32 +01:00
Sebastian Ullrich
c8c39aa4bb chore: lean-gdb: fix RC printing 2021-12-15 15:58:31 +01:00
Sebastian Ullrich
3c9ea3b113 fix: wait on tasks before Lean program exit 2021-12-15 15:58:24 +01:00
larsk21
efa2ded224 chore: bump server version to 0.1.1 2021-12-15 13:00:05 +01:00
larsk21
d50c08360d feat: change error flag to progress kind in LeanFileProgressProcessingInfo 2021-12-15 13:00:05 +01:00
larsk21
dcbc526115 feat: report header processing errors as error progress 2021-12-15 13:00:05 +01:00
larsk21
925c530673 feat: add error field to LeanFileProgressProcessingInfo 2021-12-15 13:00:05 +01:00
Siddharth
37982c6d5c doc: structure update
Co-authored-by: Sebastian Ullrich <sebasti@nullri.ch>
2021-12-15 11:48:46 +00:00
Gabriel Ebner
230d6d2cf5 fix: use group for if-then-else 2021-12-15 11:42:38 +00:00
Gabriel Ebner
202fd1414a chore: update stage0 2021-12-15 11:42:38 +00:00
Gabriel Ebner
d6f629860b feat: add ppRealFill and ppRealGroup combinators 2021-12-15 11:42:38 +00:00
Gabriel Ebner
b905824024 chore: fix tests 2021-12-15 11:42:38 +00:00
Gabriel Ebner
ab3e08190b feat: allow opt-out of grouping in formatter 2021-12-15 11:42:38 +00:00
Gabriel Ebner
b6efece612 fix: missing space after /-- 2021-12-15 11:42:38 +00:00
Gabriel Ebner
4f81972996 fix: missing newline before inductionAlt 2021-12-15 11:42:38 +00:00
Gabriel Ebner
f1fc8f2441 fix: space before where/:= in inductive 2021-12-15 11:42:38 +00:00
Gabriel Ebner
7be0d7ec16 fix: space before $ 2021-12-15 11:42:38 +00:00
Gabriel Ebner
3f73442a5a fix: space before infer modifiers 2021-12-15 11:42:38 +00:00
Gabriel Ebner
b176efefca fix: print line before deriving 2021-12-15 11:42:38 +00:00
Gabriel Ebner
5d25df1a69 fix: indenting of match arms in declValEqns 2021-12-15 11:42:38 +00:00
Gabriel Ebner
067c181075 fix: space after @& 2021-12-15 11:42:38 +00:00
Gabriel Ebner
e1b2c945e3 fix: suppress extra spaces in formatter 2021-12-15 11:42:38 +00:00
Gabriel Ebner
2b7ec7f9ef fix: spacing around (← monadic lifts) 2021-12-15 11:42:38 +00:00
Gabriel Ebner
52b36cad1d fix: whitespace around parens in open/export 2021-12-15 11:42:38 +00:00
Gabriel Ebner
87faa7a93a fix: whitespace after rw/simp [<- 2021-12-15 11:42:38 +00:00
Gabriel Ebner
f219188c95 fix: indent declaration signatures 2021-12-15 11:42:38 +00:00
Gabriel Ebner
e90bdd00db fix: indent where definitions and add space before 2021-12-15 11:42:38 +00:00
Gabriel Ebner
f5a2562575 fix: indent structure fields 2021-12-15 11:42:38 +00:00
Gabriel Ebner
316fa81042 fix: print spaces around <| and |> 2021-12-15 11:42:38 +00:00
Gabriel Ebner
f1d583c9cf fix: newline in whereDecls 2021-12-15 11:42:38 +00:00
Gabriel Ebner
448d2cd951 feat: add script to reformat lean files 2021-12-15 11:42:38 +00:00
Gabriel Ebner
7e483d3a0a feat: support syntax abbreviations in dynamic quotations 2021-12-15 11:17:58 +00:00
3094 changed files with 77497 additions and 35425 deletions

2
.gitattributes vendored
View File

@@ -1,3 +1,3 @@
*.expected.out -text
doc/changes.md merge=union
RELEASES.md merge=union
stage0/** binary linguist-generated

View File

@@ -9,12 +9,35 @@ on:
branches:
- master
schedule:
- cron: '0 0 * * *'
- cron: '0 7 * * *' # 8AM CET/11PM PT
jobs:
Build:
set-nightly:
# don't schedule nightlies on forks
if: github.event_name != 'schedule' || github.repository == 'leanprover/lean4'
if: github.event_name == 'schedule' && github.repository == 'leanprover/lean4'
runs-on: ubuntu-latest
outputs:
nightly: ${{ steps.set.outputs.nightly }}
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set Nightly
id: set
run: |
if [[ -n '${{ secrets.PUSH_NIGHTLY_TOKEN }}' ]]; then
git remote add nightly https://foo:'${{ secrets.PUSH_NIGHTLY_TOKEN }}'@github.com/${{ github.repository_owner }}/lean4-nightly.git
git fetch nightly --tags
LEAN_VERSION_STRING="nightly-$(date -u +%F)"
# do nothing if commit already has a different tag
if [[ $(git name-rev --name-only --tags --no-undefined HEAD 2> /dev/null || echo $LEAN_VERSION_STRING) == $LEAN_VERSION_STRING ]]; then
echo "::set-output name=nightly::$LEAN_VERSION_STRING"
fi
fi
build:
needs: set-nightly
# `always` *must* be used to continue even after a dependency has been skipped
if: always() && (github.event_name != 'schedule' || github.repository == 'leanprover/lean4')
runs-on: ${{ matrix.os }}
defaults:
run:
@@ -27,9 +50,11 @@ jobs:
os: ubuntu-latest
release: true
shell: nix-shell --arg pkgsDist "import (fetchTarball \"channel:nixos-19.03\") {{}}" --run "bash -euxo pipefail {0}"
llvm-url: https://github.com/leanprover/lean-llvm/releases/download/13.0.0/lean-llvm-x86_64-linux-gnu.tar.zst
prepare-llvm: script/prepare-llvm-linux.sh lean-llvm*
llvm-url: https://github.com/leanprover/lean-llvm/releases/download/14.0.0/lean-llvm-x86_64-linux-gnu.tar.zst
prepare-llvm: ../script/prepare-llvm-linux.sh lean-llvm*
binary-check: ldd -v
# foreign code may be linked against more recent glibc
CTEST_OPTIONS: -E 'foreign|leanlaketest_git'
- name: Linux
os: ubuntu-latest
check-stage3: true
@@ -41,14 +66,27 @@ jobs:
os: ubuntu-latest
# turn off custom allocator & symbolic functions to make LSAN do its magic
CMAKE_OPTIONS: -DLEAN_EXTRA_CXX_FLAGS=-fsanitize=address,undefined -DLEANC_EXTRA_FLAGS='-fsanitize=address,undefined -fsanitize-link-c++-runtime' -DSMALL_ALLOCATOR=OFF -DBSYMBOLIC=OFF
# exclude problematic tests
CTEST_OPTIONS: -E laketest
- name: macOS
os: macos-latest
release: true
shell: bash -euxo pipefail {0}
CMAKE_OPTIONS: -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15
llvm-url: https://github.com/leanprover/lean-llvm/releases/download/13.0.0/lean-llvm-x86_64-apple-darwin.tar.zst
prepare-llvm: script/prepare-llvm-macos.sh lean-llvm*
llvm-url: https://github.com/leanprover/lean-llvm/releases/download/14.0.0/lean-llvm-x86_64-apple-darwin.tar.zst
prepare-llvm: ../script/prepare-llvm-macos.sh lean-llvm*
binary-check: otool -L
tar: gtar # https://github.com/actions/runner-images/issues/2619
- name: macOS aarch64
os: macos-latest
release: true
cross: true
shell: bash -euxo pipefail {0}
CMAKE_OPTIONS: -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DUSE_GMP=OFF -DLEAN_INSTALL_SUFFIX=-darwin_aarch64
llvm-url: https://github.com/leanprover/lean-llvm/releases/download/14.0.0/lean-llvm-aarch64-apple-darwin.tar.zst https://github.com/leanprover/lean-llvm/releases/download/14.0.0/lean-llvm-x86_64-apple-darwin.tar.zst
prepare-llvm: EXTRA_FLAGS=--target=aarch64-apple-darwin ../script/prepare-llvm-macos.sh lean-llvm-aarch64-* lean-llvm-x86_64-*
binary-check: otool -L
tar: gtar # https://github.com/actions/runner-images/issues/2619
- name: Windows
os: windows-2022
release: true
@@ -56,9 +94,17 @@ jobs:
CMAKE_OPTIONS: -G "Unix Makefiles"
# for reasons unknown, interactivetests are flaky on Windows
CTEST_OPTIONS: --repeat until-pass:2
llvm-url: https://github.com/leanprover/lean-llvm/releases/download/13.0.0/lean-llvm-x86_64-w64-windows-gnu.tar.zst
prepare-llvm: script/prepare-llvm-mingw.sh lean-llvm*
llvm-url: https://github.com/leanprover/lean-llvm/releases/download/14.0.0/lean-llvm-x86_64-w64-windows-gnu.tar.zst
prepare-llvm: ../script/prepare-llvm-mingw.sh lean-llvm*
binary-check: ldd
- name: Linux aarch64
os: ubuntu-latest
CMAKE_OPTIONS: -DCMAKE_PREFIX_PATH=$GMP -DLEAN_INSTALL_SUFFIX=-linux_aarch64
release: true
cross: true
shell: nix-shell --arg pkgsDist "import (fetchTarball \"channel:nixos-19.03\") {{ localSystem.config = \"aarch64-unknown-linux-gnu\"; }}" --run "bash -euxo pipefail {0}"
llvm-url: https://github.com/leanprover/lean-llvm/releases/download/14.0.0/lean-llvm-x86_64-linux-gnu.tar.zst https://github.com/leanprover/lean-llvm/releases/download/14.0.0/lean-llvm-aarch64-linux-gnu.tar.zst
prepare-llvm: EXTRA_FLAGS=--target=aarch64-unknown-linux-gnu ../script/prepare-llvm-linux.sh lean-llvm-aarch64-* lean-llvm-x86_64-*
# complete all jobs
fail-fast: false
name: ${{ matrix.name }}
@@ -70,12 +116,13 @@ jobs:
CCACHE_MAXSIZE: 200M
# squelch error message about missing nixpkgs channel
NIX_BUILD_SHELL: bash
LSAN_OPTIONS: max_leaks=10
# somehow MinGW clang64 (or cmake?) defaults to `g++` even though it doesn't exist
CXX: c++
steps:
- name: Checkout
uses: actions/checkout@v2
with:
# interferes with lean4-nightly authentication
persist-credentials: false
submodules: true
- name: Install Nix
uses: cachix/install-nix-action@v15
@@ -84,7 +131,8 @@ jobs:
uses: msys2/setup-msys2@v2
with:
msystem: clang64
install: make python mingw-w64-clang-x86_64-cmake mingw-w64-clang-x86_64-clang mingw-w64-clang-x86_64-ccache git zip unzip diffutils binutils tree mingw-w64-clang-x86_64-zstd tar
# `:p` means prefix with appropriate msystem prefix
pacboy: "make python cmake:p clang:p ccache:p gmp:p git zip unzip diffutils binutils tree zstd:p tar"
if: matrix.os == 'windows-2022'
- name: Install Brew Packages
run: |
@@ -94,35 +142,27 @@ jobs:
uses: actions/cache@v2
with:
path: .ccache
key: ${{ matrix.name }}-build-${{ github.sha }}
key: ${{ matrix.name }}-build-v3-${{ github.sha }}
# fall back to (latest) previous cache
restore-keys: |
${{ matrix.name }}-build
${{ matrix.name }}-build-v3
- name: Setup
run: |
# open nix-shell once for initial setup
true
if: matrix.os == 'ubuntu-latest'
# remove problematic tests for sanitized build
- name: Pre build
run: rm tests/compiler/StackOverflow.lean tests/compiler/StackOverflowTask.lean
if: matrix.name == 'Linux fsanitize'
- name: Build
run: |
mkdir build
cd build
OPTIONS=()
[[ -z '${{ matrix.llvm-url }}' ]] || wget -q ${{ matrix.llvm-url }}
[[ -z '${{ matrix.prepare-llvm }}' ]] || eval "OPTIONS+=($(../${{ matrix.prepare-llvm }}))"
if [[ $GITHUB_EVENT_NAME == 'schedule' && -n '${{ matrix.release }}' && -n '${{ secrets.PUSH_NIGHTLY_TOKEN }}' ]]; then
git remote add nightly https://foo:'${{ secrets.PUSH_NIGHTLY_TOKEN }}'@github.com/${{ github.repository_owner }}/lean4-nightly.git
git fetch nightly --tags
LEAN_VERSION_STRING="nightly-$(date -u +%F)"
# do nothing if commit already has a different tag
if [[ $(git name-rev --name-only --tags --no-undefined HEAD 2> /dev/null || echo $LEAN_VERSION_STRING) == $LEAN_VERSION_STRING ]]; then
OPTIONS+=(-DLEAN_SPECIAL_VERSION_DESC=$LEAN_VERSION_STRING)
echo "LEAN_VERSION_STRING=$LEAN_VERSION_STRING" >> $GITHUB_ENV
fi
if [[ -n '${{ matrix.prepare-llvm }}' ]]; then
wget -q ${{ matrix.llvm-url }}
PREPARE="$(${{ matrix.prepare-llvm }})"
eval "OPTIONS+=($PREPARE)"
fi
if [[ -n '${{ matrix.release }}' && -n '${{ needs.set-nightly.outputs.nightly }}' ]]; then
OPTIONS+=(-DLEAN_SPECIAL_VERSION_DESC=${{ needs.set-nightly.outputs.nightly }})
fi
# contortion to support empty OPTIONS with old macOS bash
cmake .. ${{ matrix.CMAKE_OPTIONS }} ${OPTIONS[@]+"${OPTIONS[@]}"} -DLEAN_INSTALL_PREFIX=$PWD/..
@@ -133,31 +173,36 @@ jobs:
- name: List Install Tree
run: |
# omit contents of Init/, ...
tree --du -h lean-* | grep -E ' (Init|Std|Lean|Lake|LICENSE|[a-z])'
tree --du -h lean-* | grep -E ' (Init|Lean|Lake|LICENSE|[a-z])'
- name: Pack
run: |
dir=$(echo lean-*)
mkdir pack
# high-compression tar.zst + zip for release, fast tar.zst otherwise
if [[ ${{ startsWith(github.ref, 'refs/tags/v') && matrix.release }} == true || -n ${LEAN_VERSION_STRING:-} ]]; then
tar cf - $dir | zstd -T0 --no-progress -19 -o pack/$dir.tar.zst
zip -r pack/$dir.zip $dir
if [[ '${{ startsWith(github.ref, 'refs/tags/v') && matrix.release }}' == true || -n '${{ needs.set-nightly.outputs.nightly }}' ]]; then
${{ matrix.tar || 'tar' }} cf - $dir | zstd -T0 --no-progress -19 -o pack/$dir.tar.zst
zip -rq pack/$dir.zip $dir
else
tar cf - $dir | zstd -T0 --no-progress -o pack/$dir.tar.zst
${{ matrix.tar || 'tar' }} cf - $dir | zstd -T0 --no-progress -o pack/$dir.tar.zst
fi
- uses: actions/upload-artifact@v2
if: matrix.release
with:
name: build-${{ matrix.name }}
path: pack/*.zst
path: pack/*
- name: Lean stats
run: |
build/stage1/bin/lean --stats src/Lean.lean
if: ${{ !matrix.cross }}
- name: Test
run: |
cd build/stage1
ctest -j4 --output-on-failure --timeout 300 ${{ matrix.CTEST_OPTIONS }} < /dev/null
# exclude nonreproducible test
ctest -j4 --output-on-failure -E leanlaketest_git ${{ matrix.CTEST_OPTIONS }} < /dev/null
if: ${{ !matrix.cross }}
- name: Check Test Binary
run: ${{ matrix.binary-check }} tests/compiler/534.lean.out
if: ${{ !matrix.cross }}
- name: Build Stage 2
run: |
cd build
@@ -172,7 +217,8 @@ jobs:
run: |
echo -1 | sudo tee /proc/sys/kernel/perf_event_paranoid
export BUILD=$PWD/build PATH=$PWD/build/stage1/bin:$PATH
nix-shell -A with-temci --run "cd tests/bench; temci exec --config speedcenter.yaml --included_blocks fast --runs 1"
cd tests/bench
nix shell .#temci -c temci exec --config speedcenter.yaml --included_blocks fast --runs 1
if: matrix.test-speedcenter
- name: Check rebootstrap
run: |
@@ -181,40 +227,62 @@ jobs:
if: matrix.name == 'Linux'
- name: CCache stats
run: ccache -s
release:
# When GitHub says "If a job fails, all jobs that need it are skipped unless
# the jobs use a conditional expression that causes the job to continue.", don't believe
# their lies. It's actually the entire closure (i.e. including `set-nightly`) that
# must succeed for subsequent to be run without `always()`.
if: always() && needs.build.result == 'success' && startsWith(github.ref, 'refs/tags/v')
runs-on: ubuntu-latest
needs: build
steps:
- uses: actions/download-artifact@v2
with:
path: artifacts
- name: Release
uses: softprops/action-gh-release@v1
if: ${{ startsWith(github.ref, 'refs/tags/v') && matrix.release }}
with:
files: pack/*
files: artifacts/*/*
fail_on_unmatched_files: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
release-nightly:
needs: [set-nightly, build]
if: needs.set-nightly.outputs.nightly
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
with:
# needed for tagging
fetch-depth: 0
token: ${{ secrets.PUSH_NIGHTLY_TOKEN }}
- uses: actions/download-artifact@v2
with:
path: artifacts
- name: Prepare Nightly Release
if: env.LEAN_VERSION_STRING
run: |
# can't push shallow checkout
git fetch --unshallow
git remote add nightly https://foo:'${{ secrets.PUSH_NIGHTLY_TOKEN }}'@github.com/${{ github.repository_owner }}/lean4-nightly.git
git fetch nightly --tags
if git tag $LEAN_VERSION_STRING && git push nightly $LEAN_VERSION_STRING; then
last_tag=$(git describe HEAD^ --abbrev=0 --tags)
echo -e "Changes since ${last_tag}:\n\n" > diff.md
#git show $last_tag:doc/changes.md > old.md
#./script/diff_changelogs.py old.md doc/changes.md >> diff.md
echo -e "*Full commit log*\n" >> diff.md
git log --oneline $last_tag..HEAD | sed 's/^/* /' >> diff.md
else
# make sure every runner is building the same commit
[ $(git rev-parse HEAD) == $(git rev-parse $LEAN_VERSION_STRING) ] || exit 11
echo -n > diff.md
fi
git tag ${{ needs.set-nightly.outputs.nightly }}
git push nightly ${{ needs.set-nightly.outputs.nightly }}
last_tag=$(git describe HEAD^ --abbrev=0 --tags)
echo -e "*Changes since ${last_tag}:*\n\n" > diff.md
git show $last_tag:RELEASES.md > old.md
#./script/diff_changelogs.py old.md doc/changes.md >> diff.md
diff --changed-group-format='%>' --unchanged-group-format='' old.md RELEASES.md >> diff.md || true
echo -e "\n*Full commit log*\n" >> diff.md
git log --oneline $last_tag..HEAD | sed 's/^/* /' >> diff.md
- name: Release Nightly
# need unreleased version for fixed `repository`
uses: Kha/action-gh-release@master
if: env.LEAN_VERSION_STRING
uses: softprops/action-gh-release@v1
with:
body_path: diff.md
prerelease: true
files: pack/*
tag_name: ${{ env.LEAN_VERSION_STRING }}
files: artifacts/*/*
fail_on_unmatched_files: true
tag_name: ${{ needs.set-nightly.outputs.nightly }}
repository: ${{ github.repository_owner }}/lean4-nightly
env:
GITHUB_TOKEN: ${{ secrets.PUSH_NIGHTLY_TOKEN }}

View File

@@ -14,18 +14,14 @@ jobs:
runs-on: ${{ matrix.os }}
defaults:
run:
# Can't use `nix-shell` without configured nixpkgs path on macOS
shell: nix -v --experimental-features "nix-command flakes" run .#ciShell -- bash -euxo pipefail {0}
strategy:
matrix:
include:
- name: Linux
- name: Nix Linux
os: ubuntu-latest
# latest builds on https://hydra.nixos.org/jobset/nix/master/all at the time
nix_url: https://hydra.nixos.org/build/135773533/download/1/nix-2.4pre20210125_36c4d6f-x86_64-linux.tar.xz
#- name: macOS
#- name: Nix macOS
# os: macos-latest
# nix_url: https://hydra.nixos.org/build/135773542/download/1/nix-2.4pre20210125_36c4d6f-x86_64-darwin.tar.xz
# complete all jobs
fail-fast: false
name: ${{ matrix.name }}
@@ -34,39 +30,32 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v2
# Install flakes-enabled Nix manually from Hydra since `install-nix-action` doesn't accept raw tarballs
- name: Install Nix
shell: bash -euo pipefail {0}
run: |
curl ${{ matrix.nix_url }} | tar -xJ
# Do a single-user install so actions/cache doesn't get confused about permissions
nix-*/install --no-daemon --no-channel-add --darwin-use-unencrypted-nix-store-volume
rm -rf nix-*
# Call `install-nix-action` anyways to run its Actions-specific setup
- name: Setup Nix
uses: cachix/install-nix-action@v12
- name: Fixup install-nix-action
shell: bash -euo pipefail {0}
run: |
# the path set by install-nix-action is valid only for multi-user installations
echo "NIX_SSL_CERT_FILE=$HOME/.nix-profile/etc/ssl/certs/ca-bundle.crt" > $GITHUB_ENV
if: matrix.name == 'macOS'
- name: Further setup Nix
run: |
mkdir -p ~/.config/nix
echo '
max-jobs = auto
uses: cachix/install-nix-action@v15
with:
# https://github.com/NixOS/nix/issues/6572
install_url: https://releases.nixos.org/nix/nix-2.7.0/install
extra_nix_config: |
extra-sandbox-paths = /nix/var/cache/ccache
extra-substituters = file://${{ github.workspace }}/nix-store-cache?priority=10&trusted=true
extra-trusted-substituters = https://lean4.cachix.org/
extra-trusted-public-keys = lean4.cachix.org-1:mawtxSxcaiWE24xCXXgh3qnvlTkyU7evRRnGeAhD4Wk=' > ~/.config/nix/nix.conf
substituters = file://${{ github.workspace }}/nix-store-cache-copy?priority=10&trusted=true https://cache.nixos.org
- name: Set Up Nix Cache
uses: actions/cache@v2
with:
path: nix-store-cache
key: ${{ matrix.name }}-nix-store-cache-${{ github.sha }}
# fall back to (latest) previous cache
restore-keys: |
${{ matrix.name }}-nix-store-cache
- name: Further Set Up Nix Cache
shell: bash -euxo pipefail {0}
run: |
# Nix seems to mutate the cache, so make a copy
cp -r nix-store-cache nix-store-cache-copy || true
- name: Prepare CCache Cache
shell: bash -euxo pipefail {0}
run: |
sudo mkdir -m0770 -p /nix/var/cache/ccache
# macOS standard chown doesn't support --reference
nix shell .#nixpkgs.coreutils -c sudo chown --reference=/nix /nix/var/cache/ccache
echo 'max_size = 50M' > /nix/var/cache/ccache/ccache.conf
# install & use Cachix manually since `cachix-action` pushes *all* derivations (incl. `$mod-deps`, stage 2&3, etc.)
[ -z '${{ secrets.CACHIX_AUTH_TOKEN }}' ] || nix-env -iA cachix -f https://cachix.org/api/v1/install
sudo chown -R $USER /nix/var/cache/ccache
- name: Setup CCache Cache
uses: actions/cache@v2
with:
@@ -75,31 +64,32 @@ jobs:
# fall back to (latest) previous cache
restore-keys: |
${{ matrix.name }}-nix-ccache
- name: Setup Nix Cache
uses: actions/cache@v2
- name: Further Set Up CCache Cache
shell: bash -euxo pipefail {0}
run: |
sudo chown -R root:nixbld /nix/var/cache
sudo chmod -R 770 /nix/var/cache
- name: Install Cachix
uses: cachix/cachix-action@v10
with:
path: nix-store-cache
key: ${{ matrix.name }}-nix-store-cache-${{ github.sha }}
# fall back to (latest) previous cache
restore-keys: |
${{ matrix.name }}-nix-store-cache
name: lean4
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
skipPush: true # we push specific outputs only
- name: Build
run: |
# .o files are not a runtime dependency on macOS because of lack of thin archives
nix build $NIX_BUILD_ARGS .#stage0 .#stage1.lean-all .#Lean.oTree -o push-build
nix build $NIX_BUILD_ARGS .#stage0 .#stage1.lean-all .#Lean.oTree .#iTree .#modDepsFiles -o push-build
- name: Test
run: |
nix build $NIX_BUILD_ARGS .#test -o push-test
- name: Build manual
run: |
nix build $NIX_BUILD_ARGS .#mdbook .#doc-test -o push-doc
nix build $NIX_BUILD_ARGS .#doc
if: matrix.name == 'Linux'
nix build $NIX_BUILD_ARGS --update-input lean --no-write-lock-file ./doc#{lean-mdbook,leanInk,alectryon,test} -o push-doc
nix build $NIX_BUILD_ARGS --update-input lean --no-write-lock-file ./doc
if: matrix.name == 'Nix Linux'
- name: Push to Cachix
run: |
[ -z "$CACHIX_AUTH_TOKEN" ] || cachix push -j4 lean4 ./push-* || true
env:
CACHIX_AUTH_TOKEN: '${{ secrets.CACHIX_AUTH_TOKEN }}'
[ -z "${{ secrets.CACHIX_AUTH_TOKEN }}" ] || cachix push -j4 lean4 ./push-* || true
- name: Rebuild Nix Store Cache
run: |
rm -rf nix-store-cache || true
@@ -110,6 +100,9 @@ jobs:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./result
destination_dir: ./doc
if: matrix.name == 'Linux' && github.ref == 'refs/heads/master' && github.event_name == 'push'
if: matrix.name == 'Nix Linux' && github.ref == 'refs/heads/master' && github.event_name == 'push'
- name: Fixup CCache Cache
run: |
sudo chown -R $USER /nix/var/cache
- name: CCache stats
run: CCACHE_DIR=/nix/var/cache/ccache nix run .#nixpkgs.ccache -- -s

1
.ignore Normal file
View File

@@ -0,0 +1 @@
stage0/

View File

@@ -3,9 +3,15 @@ This is the repository for **Lean 4**, which is currently being released as mile
# About
- [Quickstart](https://github.com/leanprover/lean4/blob/master/doc/quickstart.md)
- [Walkthrough installation video](https://www.youtube.com/watch?v=yZo6k48L0VY)
- [Quick tour video](https://youtu.be/zyXtbb_eYbY)
- [Homepage](https://leanprover.github.io)
- [Theorem Proving Tutorial](https://leanprover.github.io/theorem_proving_in_lean4/)
- [Functional Programming in Lean](https://leanprover.github.io/functional_programming_in_lean/) **first chapter is available!**
- [Manual](https://leanprover.github.io/lean4/doc/)
- [Release notes](RELEASES.md) starting at v4.0.0-m3
- [Examples](https://leanprover.github.io/lean4/doc/examples.html)
- [FAQ](https://leanprover.github.io/lean4/doc/faq.html)
# Installation

1008
RELEASES.md Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,3 @@
import Std
open Std
open Lean
@@ -104,9 +103,9 @@ syntax entry := ident " ↦ " term:max
syntax entry,* "" term : term
macro_rules
| `( $[$xs:ident $vs:term],* $p:term ) =>
| `( $[$xs $vs],* $p) =>
let xs := xs.map fun x => quote x.getId.toString
`(denote (List.toAssocList [$[( $xs , $vs )],*]) `[BExpr| $p])
`(denote (List.toAssocList [$[($xs, $vs)],*]) `[BExpr| $p])
#check b true b b
#eval a false, b false b a

View File

@@ -2,32 +2,44 @@
- [What is Lean](./whatIsLean.md)
- [Tour of Lean](./tour.md)
- [Setting Up Lean](./setup.md)
- [Quickstart](./quickstart.md)
- [Setting Up Lean](./quickstart.md)
- [Extended Setup Notes](./setup.md)
- [Theorem Proving in Lean](./tpil.md)
- [Functional Programming in Lean](fplean.md)
- [Examples](./examples.md)
- [Palindromes](examples/palindromes.lean.md)
- [Binary Search Trees](examples/bintree.lean.md)
- [A Certified Type Checker](examples/tc.lean.md)
- [The Well-Typed Interpreter](examples/interp.lean.md)
- [Dependent de Bruijn Indices](examples/deBruijn.lean.md)
- [Parametric Higher-Order Abstract Syntax](examples/phoas.lean.md)
# Language Manual
- [Using Lean](./using_lean.md)
- [Lexical Structure](./lexical_structure.md)
- [Expressions](./expressions.md)
- [Declarations](./declarations.md)
<!-- - [Using Lean](./using_lean.md) -->
<!-- - [Lexical Structure](./lexical_structure.md) -->
<!-- - [Expressions](./expressions.md) -->
<!-- - [Declarations](./declarations.md) -->
- [Organizational features](./organization.md)
- [Sections](./sections.md)
- [Namespaces](./namespaces.md)
- [Implicit Arguments](./implicit.md)
- [Auto Bound Implicit Arguments](./autobound.md)
- [Dependent Types](./deptypes.md)
- [Simple Type Theory](./simptypes.md)
- [Types as objects](./typeobjs.md)
- [Function Abstraction and Evaluation](./funabst.md)
- [Introducing Definitions](./introdef.md)
- [What makes dependent type theory dependent?](./dep.md)
- [Tactics](./tactics.md)
<!-- - [Dependent Types](./deptypes.md) -->
<!-- - [Simple Type Theory](./simptypes.md) -->
<!-- - [Types as objects](./typeobjs.md) -->
<!-- - [Function Abstraction and Evaluation](./funabst.md) -->
<!-- - [Introducing Definitions](./introdef.md) -->
<!-- - [What makes dependent type theory dependent?](./dep.md) -->
<!-- - [Tactics](./tactics.md) -->
- [Syntax Extensions](./syntax.md)
- [The `do` Notation](./do.md)
- [User-defined notation](./notation.md)
- [String Interpolation](./stringinterp.md)
- [User-Defined Notation](./notation.md)
- [Macro Overview](./macro_overview.md)
- [A Guided Example](./syntax_example.md)
- [Elaborators](./elaborators.md)
- [Examples](./syntax_examples.md)
- [Balanced Parentheses](./syntax_example.md)
- [Arithmetic DSL](./metaprogramming-arith.md)
- [Declaring New Types](./decltypes.md)
- [Enumerated Types](./enum.md)
- [Inductive Types](./inductive.md)
@@ -47,27 +59,35 @@
- [Thunk](./thunk.md)
- [Task and Thread](./task.md)
- [Functions](./functions.md)
- [Tactics](./tactics.md)
- [Monads](./monads/intro.md)
- [Functor](./monads/functors.lean.md)
- [Applicative](./monads/applicatives.lean.md)
- [Monad](./monads/monads.lean.md)
- [Reader](./monads/readers.lean.md)
- [State](./monads/states.lean.md)
- [Except](./monads/except.lean.md)
- [Transformers](./monads/transformers.lean.md)
- [Laws](./monads/laws.lean.md)
# Other
- [Frequently Asked Questions](./faq.md)
- [Significant Changes from Lean 3](./lean3changes.md)
- [Syntax Highlighting Lean in LaTeX](./syntax_highlight_in_latex.md)
- [User Widgets](examples/widgets.lean.md)
# Development
- [Development Guide](./dev/index.md)
- [Commit Convention](./dev/commit_convention.md)
- [Building Lean](./make/index.md)
- [Ubuntu Setup](./make/ubuntu.md)
- [macOS Setup](./make/osx-10.9.md)
- [Windows MSYS2 Setup](./make/msys2.md)
- [Windows with WSL](./make/wsl.md)
- [Nix Setup (*Experimental*)](./make/nix.md)
- [Foreign Function Interface](./dev/ffi.md)
- [Unit Testing](./dev/testing.md)
- [Building This Manual](./dev/mdbook.md)
- [Fixing Tests](./dev/fixing_tests.md)
- [Bootstrapping](./dev/bootstrap.md)
- [Testing](./dev/testing.md)
- [Debugging](./dev/debugging.md)
- [C++ Coding Style](./dev/cpp_coding_style.md)
- [Commit Convention](./dev/commit_convention.md)
- [Building This Manual](./dev/mdbook.md)
- [Foreign Function Interface](./dev/ffi.md)

786
doc/alectryon.css Normal file
View File

@@ -0,0 +1,786 @@
@charset "UTF-8";
/*
Copyright © 2019 Clément Pit-Claudel
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/*******************************/
/* CSS reset for .alectryon-io */
/*******************************/
.content {
/*
Use `initial` instead of `contents` to avoid a browser bug which removes
the element from the accessibility tree.
https://developer.mozilla.org/en-US/docs/Web/CSS/display#display_contents
*/
display: initial;
}
.alectryon-io blockquote {
line-height: inherit;
}
.alectryon-io blockquote:after {
display: none;
}
.alectryon-io label {
display: inline;
font-size: inherit;
margin: 0;
}
.alectryon-io a {
text-decoration: none !important;
font-style: oblique !important;
color: unset;
}
/* Undo <small> and <blockquote>, added to improve RSS rendering. */
.alectryon-io small.alectryon-output,
.alectryon-io small.alectryon-type-info {
font-size: inherit;
}
.alectryon-io blockquote.alectryon-goal,
.alectryon-io blockquote.alectryon-message {
font-weight: normal;
font-size: inherit;
}
/***************/
/* Main styles */
/***************/
.alectryon-coqdoc .doc .code,
.alectryon-coqdoc .doc .comment,
.alectryon-coqdoc .doc .inlinecode,
.alectryon-mref,
.alectryon-block, .alectryon-io,
.alectryon-toggle-label, .alectryon-banner {
font-family: "Source Code Pro", Consolas, "Ubuntu Mono", Menlo, "DejaVu Sans Mono", monospace, monospace !important;
font-size: 0.875em;
font-feature-settings: "COQX" 1 /* Coq ligatures */, "XV00" 1 /* Legacy */, "calt" 1 /* Fallback */;
line-height: initial;
}
.alectryon-io, .alectryon-block, .alectryon-toggle-label, .alectryon-banner {
overflow: visible;
overflow-wrap: break-word;
position: relative;
white-space: pre-wrap;
}
/*
CoqIDE doesn't turn off the unicode bidirectional algorithm (and PG simply
respects the user's `bidi-display-reordering` setting), so don't turn it off
here either. But beware unexpected results like `Definition test_אב := 0.`
.alectryon-io span {
direction: ltr;
unicode-bidi: bidi-override;
}
In any case, make an exception for comments:
.highlight .c {
direction: embed;
unicode-bidi: initial;
}
*/
.alectryon-mref,
.alectryon-mref-marker {
align-self: center;
box-sizing: border-box;
display: inline-block;
font-size: 80%;
font-weight: bold;
line-height: 1;
box-shadow: 0 0 0 1pt black;
padding: 1pt 0.3em;
text-decoration: none;
}
.alectryon-block .alectryon-mref-marker,
.alectryon-io .alectryon-mref-marker {
user-select: none;
margin: -0.25em 0 -0.25em 0.5em;
}
.alectryon-inline .alectryon-mref-marker {
margin: -0.25em 0.15em -0.25em 0.625em; /* 625 = 0.5em / 80% */
}
.alectryon-mref {
color: inherit;
margin: -0.5em 0.25em;
}
.alectryon-goal:target .goal-separator .alectryon-mref-marker,
:target > .alectryon-mref-marker {
animation: blink 0.2s step-start 0s 3 normal none;
background-color: #fcaf3e;
position: relative;
}
@keyframes blink {
50% {
box-shadow: 0 0 0 3pt #fcaf3e, 0 0 0 4pt black;
z-index: 10;
}
}
.alectryon-toggle,
.alectryon-io .alectryon-extra-goal-toggle {
display: none;
}
.alectryon-bubble,
.alectryon-io label,
.alectryon-toggle-label {
cursor: pointer;
}
.alectryon-toggle-label {
display: block;
font-size: 0.8em;
}
.alectryon-io .alectryon-input {
padding: 0.1em 0; /* Enlarge the hitbox slightly to fill interline gaps */
}
.alectryon-io .alectryon-token {
white-space: pre-wrap;
display: inline;
}
.alectryon-io .alectryon-sentence.alectryon-target .alectryon-input {
/* FIXME if keywords were bolder we wouldn't need !important */
font-weight: bold !important; /* Use !important to avoid a * selector */
}
.alectryon-bubble:before,
.alectryon-toggle-label:before,
.alectryon-io label.alectryon-input:after,
.alectryon-io .alectryon-goal > label:before {
border: 1px solid #babdb6;
border-radius: 1em;
box-sizing: border-box;
content: '';
display: inline-block;
font-weight: bold;
height: 0.25em;
margin-bottom: 0.15em;
vertical-align: middle;
width: 0.75em;
}
.alectryon-toggle-label:before,
.alectryon-io .alectryon-goal > label:before {
margin-right: 0.25em;
}
.alectryon-io .alectryon-goal > label:before {
margin-top: 0.125em;
}
.alectryon-io label.alectryon-input {
padding-right: 1em; /* Prevent line wraps before the checkbox bubble */
}
.alectryon-io label.alectryon-input:after {
margin-left: 0.25em;
margin-right: -1em; /* Compensate for the anti-wrapping space */
}
.alectryon-failed {
/* Underlines are broken in Chrome (they reset at each element boundary)… */
/* text-decoration: red wavy underline; */
/* … but it isn't too noticeable with dots */
text-decoration: red dotted underline;
text-decoration-skip-ink: none;
/* Chrome prints background images in low resolution, yielding a blurry underline */
/* background: bottom / 0.3em auto repeat-x url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyLjY0NiAxLjg1MiIgaGVpZ2h0PSI4IiB3aWR0aD0iMTAiPjxwYXRoIGQ9Ik0wIC4yNjVjLjc5NCAwIC41MyAxLjMyMiAxLjMyMyAxLjMyMi43OTQgMCAuNTMtMS4zMjIgMS4zMjMtMS4zMjIiIGZpbGw9Im5vbmUiIHN0cm9rZT0icmVkIiBzdHJva2Utd2lkdGg9Ii41MjkiLz48L3N2Zz4=); */
}
/* Wrapping :hover rules in a media query ensures that tapping a Coq sentence
doesn't trigger its :hover state (otherwise, on mobile, tapping a sentence to
hide its output causes it to remain visible (its :hover state gets triggered.
We only do it for the default style though, since other styles don't put the
output over the main text, so showing too much is not an issue. */
@media (any-hover: hover) {
.alectryon-bubble:hover:before,
.alectryon-toggle-label:hover:before,
.alectryon-io label.alectryon-input:hover:after {
background: #eeeeec;
}
.alectryon-io label.alectryon-input:hover {
text-decoration: underline dotted #babdb6;
text-shadow: 0 0 1px rgb(46, 52, 54, 0.3); /* #2e3436 + opacity */
}
.alectryon-io .alectryon-sentence:hover .alectryon-output,
.alectryon-io .alectryon-token:hover .alectryon-type-info-wrapper,
.alectryon-io .alectryon-token:hover .alectryon-type-info-wrapper {
z-index: 2; /* Place hovered goals above .alectryon-sentence.alectryon-target ones */
}
}
.alectryon-toggle:checked + .alectryon-toggle-label:before,
.alectryon-io .alectryon-sentence > .alectryon-toggle:checked + label.alectryon-input:after,
.alectryon-io .alectryon-extra-goal-toggle:checked + .alectryon-goal > label:before {
background-color: #babdb6;
border-color: #babdb6;
}
/* Disable clicks on sentences when the document-wide toggle is set. */
.alectryon-toggle:checked + label + .alectryon-container label.alectryon-input {
cursor: unset;
pointer-events: none;
}
/* Hide individual checkboxes when the document-wide toggle is set. */
.alectryon-toggle:checked + label + .alectryon-container label.alectryon-input:after {
display: none;
}
/* .alectryon-output is displayed by toggles, :hover, and .alectryon-target rules */
.alectryon-io .alectryon-output {
box-sizing: border-box;
display: none;
left: 0;
right: 0;
position: absolute;
padding: 0.25em 0;
overflow: visible; /* Let box-shadows overflow */
z-index: 1; /* Default to an index lower than that used by :hover */
}
.alectryon-io .alectryon-type-info-wrapper {
position: absolute;
display: inline-block;
width: 100%;
}
.alectryon-io .alectryon-type-info-wrapper.full-width {
left: 0;
min-width: 100%;
max-width: 100%;
}
.alectryon-io .alectryon-type-info .goal-separator {
height: unset;
margin-top: 0em;
}
.alectryon-io .alectryon-type-info-wrapper .alectryon-type-info {
box-sizing: border-box;
bottom: 100%;
position: absolute;
/*padding: 0.25em 0;*/
visibility: hidden;
overflow: visible; /* Let box-shadows overflow */
z-index: 1; /* Default to an index lower than that used by :hover */
white-space: pre-wrap !important;
}
.alectryon-io .alectryon-type-info-wrapper .alectryon-type-info .alectryon-goal.alectryon-docstring {
white-space: pre-wrap !important;
}
@media (any-hover: hover) { /* See note above about this @media query */
.alectryon-io .alectryon-sentence:hover .alectryon-output:not(:hover) {
display: block;
}
.alectryon-io.output-hidden .alectryon-sentence:hover .alectryon-output:not(:hover) {
display: none !important;
}
.alectryon-io.type-info-hidden .alectryon-token:hover .alectryon-type-info-wrapper .alectryon-type-info,
.alectryon-io.type-info-hidden .alectryon-token:hover .alectryon-type-info-wrapper .alectryon-type-info {
/*visibility: hidden !important;*/
}
.alectryon-io .alectryon-token:hover .alectryon-type-info-wrapper .alectryon-type-info,
.alectryon-io .alectryon-token:hover .alectryon-type-info-wrapper .alectryon-type-info {
visibility: visible;
transition-delay: 0.5s;
}
}
.alectryon-io .alectryon-sentence.alectryon-target .alectryon-output {
display: block;
}
/* Indicate active (hovered or targeted) goals with a shadow. */
.alectryon-io .alectryon-sentence:hover .alectryon-output:not(:hover) .alectryon-messages,
.alectryon-io .alectryon-sentence.alectryon-target .alectryon-output .alectryon-messages,
.alectryon-io .alectryon-sentence:hover .alectryon-output:not(:hover) .alectryon-goals,
.alectryon-io .alectryon-sentence.alectryon-target .alectryon-output .alectryon-goals,
.alectryon-io .alectryon-token:hover .alectryon-type-info-wrapper .alectryon-type-info {
box-shadow: 2px 2px 2px gray;
}
.alectryon-io .alectryon-extra-goals .alectryon-goal .goal-hyps {
display: none;
}
.alectryon-io .alectryon-extra-goals .alectryon-extra-goal-toggle:not(:checked) + .alectryon-goal label.goal-separator hr {
/* Dashes indicate that the hypotheses are hidden */
border-top-style: dashed;
}
/* Show just a small preview of the other goals; this is undone by the
"extra-goal" toggle and by :hover and .alectryon-target in windowed mode. */
.alectryon-io .alectryon-extra-goals .alectryon-goal .goal-conclusion {
max-height: 5.2em;
overflow-y: auto;
/* Combining overflow-y: auto with display: inline-block causes extra space
to be added below the box. vertical-align: middle gets rid of it. */
vertical-align: middle;
}
.alectryon-io .alectryon-goals,
.alectryon-io .alectryon-messages {
background: #f6f7f6;
/*border: thin solid #d3d7cf; /* Convenient when pre's background is already #EEE */
display: block;
padding: 0.25em;
}
.alectryon-message::before {
content: '';
float: right;
/* etc/svg/square-bubble-xl.svg */
background: url("data:image/svg+xml,%3Csvg width='14' height='14' viewBox='0 0 3.704 3.704' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill-rule='evenodd' stroke='%23000' stroke-width='.264'%3E%3Cpath d='M.794.934h2.115M.794 1.463h1.455M.794 1.992h1.852'/%3E%3C/g%3E%3Cpath d='M.132.14v2.646h.794v.661l.926-.661h1.72V.14z' fill='none' stroke='%23000' stroke-width='.265'/%3E%3C/svg%3E") top right no-repeat;
height: 14px;
width: 14px;
}
.alectryon-toggle:checked + label + .alectryon-container {
width: unset;
}
/* Show goals when a toggle is set */
.alectryon-toggle:checked + label + .alectryon-container label.alectryon-input + .alectryon-output,
.alectryon-io .alectryon-sentence > .alectryon-toggle:checked ~ .alectryon-output {
display: block;
position: static;
width: unset;
background: unset; /* Override the backgrounds set in floating in windowed mode */
padding: 0.25em 0; /* Re-assert so that later :hover rules don't override this padding */
}
.alectryon-toggle:checked + label + .alectryon-container label.alectryon-input + .alectryon-output .goal-hyps,
.alectryon-io .alectryon-sentence > .alectryon-toggle:checked ~ .alectryon-output .goal-hyps {
/* Overridden back in windowed style */
flex-flow: row wrap;
justify-content: flex-start;
}
.alectryon-toggle:checked + label + .alectryon-container .alectryon-sentence .alectryon-output > div,
.alectryon-io .alectryon-sentence > .alectryon-toggle:checked ~ .alectryon-output > div {
display: block;
}
.alectryon-io .alectryon-extra-goal-toggle:checked + .alectryon-goal .goal-hyps {
display: flex;
}
.alectryon-io .alectryon-extra-goal-toggle:checked + .alectryon-goal .goal-conclusion {
max-height: unset;
overflow-y: unset;
}
.alectryon-toggle:checked + label + .alectryon-container .alectryon-sentence > .alectryon-toggle ~ .alectryon-wsp,
.alectryon-io .alectryon-sentence > .alectryon-toggle:checked ~ .alectryon-wsp {
display: none;
}
.alectryon-io .alectryon-messages,
.alectryon-io .alectryon-message,
.alectryon-io .alectryon-goals,
.alectryon-io .alectryon-goal,
.alectryon-io .goal-hyps > span,
.alectryon-io .goal-conclusion {
border-radius: 0.15em;
}
.alectryon-io .alectryon-goal,
.alectryon-io .alectryon-message {
align-items: center;
background: #f6f7f6;
border: 0em;
display: block;
flex-direction: column;
margin: 0.25em;
padding: 0.5em;
position: relative;
}
.alectryon-io .goal-hyps {
align-content: space-around;
align-items: baseline;
display: flex;
flex-flow: column nowrap; /* re-stated in windowed mode */
justify-content: space-around;
/* LATER use a gap property instead of margins once supported */
margin: -0.15em -0.25em; /* -0.15em to cancel the item spacing */
padding-bottom: 0.35em; /* 0.5em-0.15em to cancel the 0.5em of .goal-separator */
}
.alectryon-io .goal-hyps > br {
display: none; /* Only for RSS readers */
}
.alectryon-io .goal-hyps > span,
.alectryon-io .goal-conclusion {
/*background: #eeeeec;*/
display: inline-block;
padding: 0.15em 0.35em;
}
.alectryon-io .goal-hyps > span {
align-items: baseline;
display: inline-flex;
margin: 0.15em 0.25em;
}
.alectryon-block var,
.alectryon-inline var,
.alectryon-io .goal-hyps > span > var {
font-weight: 600;
font-style: unset;
}
.alectryon-io .goal-hyps > span > var {
/* Shrink the list of names, but let it grow as long as space is available. */
flex-basis: min-content;
flex-grow: 1;
}
.alectryon-io .goal-hyps > span b {
font-weight: 600;
margin: 0 0 0 0.5em;
white-space: pre;
}
.alectryon-io .hyp-body,
.alectryon-io .hyp-type {
display: flex;
align-items: baseline;
}
.alectryon-io .goal-separator {
align-items: center;
display: flex;
flex-direction: row;
height: 1em; /* Fixed height to ignore goal name and markers */
margin-top: -0.5em; /* Compensated in .goal-hyps when shown */
}
.alectryon-io .goal-separator hr {
border: none;
border-top: thin solid #555753;
display: block;
flex-grow: 1;
margin: 0;
}
.alectryon-io .goal-separator .goal-name {
font-size: 0.75em;
margin-left: 0.5em;
}
/**********/
/* Banner */
/**********/
.alectryon-banner {
background: #eeeeec;
border: 1px solid #babcbd;
font-size: 0.75em;
padding: 0.25em;
text-align: center;
margin: 1em 0;
}
.alectryon-banner a {
cursor: pointer;
text-decoration: underline;
}
.alectryon-banner kbd {
background: #d3d7cf;
border-radius: 0.15em;
border: 1px solid #babdb6;
box-sizing: border-box;
display: inline-block;
font-family: inherit;
font-size: 0.9em;
height: 1.3em;
line-height: 1.2em;
margin: -0.25em 0;
padding: 0 0.25em;
vertical-align: middle;
}
/**********/
/* Toggle */
/**********/
.alectryon-toggle-label {
margin: 1rem 0;
}
/******************/
/* Floating style */
/******************/
/* If there's space, display goals to the right of the code, not below it. */
@media (min-width: 80rem) {
/* Unlike the windowed case, we don't want to move output blocks to the side
when they are both :checked and -targeted, since it gets confusing as
things jump around; hence the commented-output part of the selector,
which would otherwise increase specificity */
.alectryon-floating .alectryon-sentence.alectryon-target /* > .alectryon-toggle ~ */ .alectryon-output,
.alectryon-floating .alectryon-sentence:hover .alectryon-output {
top: 0;
left: 100%;
right: -100%;
padding: 0 0.5em;
position: absolute;
}
.alectryon-floating .alectryon-output {
min-height: 100%;
}
.alectryon-floating .alectryon-sentence:hover .alectryon-output {
background: white; /* Ensure that short goals hide long ones */
}
/* This odd margin-bottom property prevents the sticky div from bumping
against the bottom of its container (.alectryon-output). The alternative
would be enlarging .alectryon-output, but that would cause overflows,
enlarging scrollbars and yielding scrolling towards the bottom of the
page. Doing things this way instead makes it possible to restrict
.alectryon-output to a reasonable size (100%, through top = bottom = 0).
See also https://stackoverflow.com/questions/43909940/. */
/* See note on specificity above */
.alectryon-floating .alectryon-sentence.alectryon-target /* > .alectryon-toggle ~ */ .alectryon-output > div,
.alectryon-floating .alectryon-sentence:hover .alectryon-output > div {
margin-bottom: -200%;
position: sticky;
top: 0;
}
.alectryon-floating .alectryon-toggle:checked + label + .alectryon-container .alectryon-sentence .alectryon-output > div,
.alectryon-floating .alectryon-io .alectryon-sentence > .alectryon-toggle:checked ~ .alectryon-output > div {
margin-bottom: unset; /* Undo the margin */
}
/* Float underneath the current fragment
@media (max-width: 80rem) {
.alectryon-floating .alectryon-output {
top: 100%;
}
} */
}
/********************/
/* Multi-pane style */
/********************/
.alectryon-windowed {
border: 0 solid #2e3436;
box-sizing: border-box;
}
.alectryon-windowed .alectryon-sentence:hover .alectryon-output {
background: white; /* Ensure that short goals hide long ones */
}
.alectryon-windowed .alectryon-output {
position: fixed; /* Overwritten by the :checked rules */
}
/* See note about specificity below */
.alectryon-windowed .alectryon-sentence:hover .alectryon-output,
.alectryon-windowed .alectryon-sentence.alectryon-target > .alectryon-toggle ~ .alectryon-output {
padding: 0.5em;
overflow-y: auto; /* Windowed contents may need to scroll */
}
.alectryon-windowed .alectryon-io .alectryon-sentence:hover .alectryon-output:not(:hover) .alectryon-messages,
.alectryon-windowed .alectryon-io .alectryon-sentence.alectryon-target .alectryon-output .alectryon-messages,
.alectryon-windowed .alectryon-io .alectryon-sentence:hover .alectryon-output:not(:hover) .alectryon-goals,
.alectryon-windowed .alectryon-io .alectryon-sentence.alectryon-target .alectryon-output .alectryon-goals {
box-shadow: none; /* A shadow is unnecessary here and incompatible with overflow-y set to auto */
}
.alectryon-windowed .alectryon-io .alectryon-sentence.alectryon-target .alectryon-output .goal-hyps {
/* Restated to override the :checked style */
flex-flow: column nowrap;
justify-content: space-around;
}
.alectryon-windowed .alectryon-sentence.alectryon-target .alectryon-extra-goals .alectryon-goal .goal-conclusion
/* Like .alectryon-io .alectryon-extra-goal-toggle:checked + .alectryon-goal .goal-conclusion */ {
max-height: unset;
overflow-y: unset;
}
.alectryon-windowed .alectryon-output > div {
display: flex; /* Put messages after goals */
flex-direction: column-reverse;
}
/*********************/
/* Standalone styles */
/*********************/
.alectryon-standalone {
font-family: 'IBM Plex Serif', 'PT Serif', 'Merriweather', 'DejaVu Serif', serif;
line-height: 1.5;
}
@media screen and (min-width: 50rem) {
html.alectryon-standalone {
/* Prevent flickering when hovering a block causes scrollbars to appear. */
margin-left: calc(100vw - 100%);
margin-right: 0;
}
}
/* Coqdoc */
.alectryon-coqdoc .doc .code,
.alectryon-coqdoc .doc .inlinecode,
.alectryon-coqdoc .doc .comment {
display: inline;
}
.alectryon-coqdoc .doc .comment {
color: #eeeeec;
}
.alectryon-coqdoc .doc .paragraph {
height: 0.75em;
}
/* Centered, Floating */
.alectryon-standalone .alectryon-centered,
.alectryon-standalone .alectryon-floating {
max-width: 50rem;
margin: auto;
}
@media (min-width: 80rem) {
.alectryon-standalone .alectryon-floating {
max-width: 80rem;
}
.alectryon-standalone .alectryon-floating > * {
width: 50%;
margin-left: 0;
}
}
/* Windowed */
.alectryon-standalone .alectryon-windowed {
display: block;
margin: 0;
overflow-y: auto;
position: absolute;
padding: 0 1em;
}
.alectryon-standalone .alectryon-windowed > * {
/* Override properties of docutils_basic.css */
margin-left: 0;
max-width: unset;
}
.alectryon-standalone .alectryon-windowed .alectryon-io {
box-sizing: border-box;
width: 100%;
}
/* No need to predicate the :hover rules below on :not(:checked), since left,
right, top, and bottom will be inactived by the :checked rules setting
position to static */
/* Specificity: We want the output to stay inline when hovered while unfolded
(:checked), but we want it to move when it's targeted (i.e. when the user
is browsing goals one by one using the keyboard, in which case we want to
goals to appear in consistent locations). The selectors below ensure
that :hover < :checked < -targeted in terms of specificity. */
/* LATER: Reimplement this stuff with CSS variables */
.alectryon-windowed .alectryon-sentence.alectryon-target > .alectryon-toggle ~ .alectryon-output {
position: fixed;
}
@media screen and (min-width: 60rem) {
.alectryon-standalone .alectryon-windowed {
border-right-width: thin;
bottom: 0;
left: 0;
right: 50%;
top: 0;
}
.alectryon-standalone .alectryon-windowed .alectryon-sentence:hover .alectryon-output,
.alectryon-standalone .alectryon-windowed .alectryon-sentence.alectryon-target .alectryon-output {
bottom: 0;
left: 50%;
right: 0;
top: 0;
}
}
@media screen and (max-width: 60rem) {
.alectryon-standalone .alectryon-windowed {
border-bottom-width: 1px;
bottom: 40%;
left: 0;
right: 0;
top: 0;
}
.alectryon-standalone .alectryon-windowed .alectryon-sentence:hover .alectryon-output,
.alectryon-standalone .alectryon-windowed .alectryon-sentence.alectryon-target .alectryon-output {
bottom: 0;
left: 0;
right: 0;
top: 60%;
}
}

190
doc/alectryon.js Normal file
View File

@@ -0,0 +1,190 @@
var Alectryon;
(function(Alectryon) {
(function (slideshow) {
function anchor(sentence) { return "#" + sentence.id; }
function current_sentence() { return slideshow.sentences[slideshow.pos]; }
function unhighlight() {
var sentence = current_sentence();
if (sentence) sentence.classList.remove("alectryon-target");
slideshow.pos = -1;
}
function highlight(sentence) {
sentence.classList.add("alectryon-target");
}
function scroll(sentence) {
// Put the top of the current fragment close to the top of the
// screen, but scroll it out of view if showing it requires pushing
// the sentence past half of the screen. If sentence is already in
// a reasonable position, don't move.
var parent = sentence.parentElement;
/* We want to scroll the whole document, so start at root… */
while (parent && !parent.classList.contains("alectryon-root"))
parent = parent.parentElement;
/* … and work up from there to find a scrollable element.
parent.scrollHeight can be greater than parent.clientHeight
without showing scrollbars, so we add a 10px buffer. */
while (parent && parent.scrollHeight <= parent.clientHeight + 10)
parent = parent.parentElement;
/* <body> and <html> elements can have their client rect overflow
* the window if their height is unset, so scroll the window
* instead */
if (parent && (parent.nodeName == "BODY" || parent.nodeName == "HTML"))
parent = null;
var rect = function(e) { return e.getBoundingClientRect(); };
var parent_box = parent ? rect(parent) : { y: 0, height: window.innerHeight },
sentence_y = rect(sentence).y - parent_box.y,
fragment_y = rect(sentence.parentElement).y - parent_box.y;
// The assertion below sometimes fails for the first element in a block.
// console.assert(sentence_y >= fragment_y);
if (sentence_y < 0.1 * parent_box.height ||
sentence_y > 0.7 * parent_box.height) {
(parent || window).scrollBy(
0, Math.max(sentence_y - 0.5 * parent_box.height,
fragment_y - 0.1 * parent_box.height));
}
}
function highlighted(pos) {
return slideshow.pos == pos;
}
function navigate(pos, inhibitScroll) {
unhighlight();
slideshow.pos = Math.min(Math.max(pos, 0), slideshow.sentences.length - 1);
var sentence = current_sentence();
highlight(sentence);
if (!inhibitScroll)
scroll(sentence);
}
var keys = {
PAGE_UP: 33,
PAGE_DOWN: 34,
ARROW_UP: 38,
ARROW_DOWN: 40,
h: 72, l: 76, p: 80, n: 78
};
function onkeydown(e) {
e = e || window.event;
if (e.ctrlKey || e.metaKey) {
if (e.keyCode == keys.ARROW_UP)
slideshow.previous();
else if (e.keyCode == keys.ARROW_DOWN)
slideshow.next();
else
return;
} else {
// if (e.keyCode == keys.PAGE_UP || e.keyCode == keys.p || e.keyCode == keys.h)
// slideshow.previous();
// else if (e.keyCode == keys.PAGE_DOWN || e.keyCode == keys.n || e.keyCode == keys.l)
// slideshow.next();
// else
return;
}
e.preventDefault();
}
function start() {
slideshow.navigate(0);
}
function toggleHighlight(idx) {
if (highlighted(idx))
unhighlight();
else
navigate(idx, true);
}
function handleClick(evt) {
if (evt.ctrlKey || evt.metaKey) {
var sentence = evt.currentTarget;
// Ensure that the goal is shown on the side, not inline
var checkbox = sentence.getElementsByClassName("alectryon-toggle")[0];
if (checkbox)
checkbox.checked = false;
toggleHighlight(sentence.alectryon_index);
evt.preventDefault();
}
}
function init() {
document.onkeydown = onkeydown;
slideshow.pos = -1;
slideshow.sentences = Array.from(document.getElementsByClassName("alectryon-sentence"));
slideshow.sentences.forEach(function (s, idx) {
s.addEventListener('click', handleClick, false);
s.alectryon_index = idx;
});
}
slideshow.start = start;
slideshow.end = unhighlight;
slideshow.navigate = navigate;
slideshow.next = function() { navigate(slideshow.pos + 1); };
slideshow.previous = function() { navigate(slideshow.pos + -1); };
window.addEventListener('DOMContentLoaded', init);
})(Alectryon.slideshow || (Alectryon.slideshow = {}));
(function (styles) {
var styleNames = ["centered", "floating", "windowed"];
function className(style) {
return "alectryon-" + style;
}
function setStyle(style) {
var root = document.getElementsByClassName("alectryon-root")[0];
styleNames.forEach(function (s) {
root.classList.remove(className(s)); });
root.classList.add(className(style));
}
function init() {
var banner = document.getElementsByClassName("alectryon-banner")[0];
if (banner) {
banner.append(" Style: ");
styleNames.forEach(function (styleName, idx) {
var s = styleName;
var a = document.createElement("a");
a.onclick = function() { setStyle(s); };
a.append(styleName);
if (idx > 0) banner.append("; ");
banner.appendChild(a);
});
banner.append(".");
}
}
window.addEventListener('DOMContentLoaded', init);
styles.setStyle = setStyle;
})(Alectryon.styles || (Alectryon.styles = {}));
})(Alectryon || (Alectryon = {}));
function setHidden(elements, isVisible, token) {
for (let i = 0; i < elements.length; i++) {
if (isVisible) {
elements[i].classList.remove(token)
} else {
elements[i].classList.add(token)
}
}
}
function toggleShowTypes(checkbox) {
setHidden(document.getElementsByClassName("alectryon-io"), checkbox.checked, "type-info-hidden")
}
function toggleShowGoals(checkbox) {
setHidden(document.getElementsByClassName("alectryon-io"), checkbox.checked, "output-hidden")
}

View File

@@ -39,16 +39,17 @@ To create an array of size `n` in which all the elements are initialized to some
You can access array elements by using brackets (`[` and `]`).
```lean
#eval #['a', 'b', 'c'][1]
-- 'b'
def getThird (xs : Array Nat) : Nat :=
xs[2]
#eval getThird #[10, 20, 30, 40]
-- 30
def f (a : Array Nat) (i : Fin a.size) :=
a[i] + a[i]
```
Note that the index `i` has type `Fin a.size`, i.e., it is natural number less than `a.size`.
You can also write
```lean
def f (a : Array Nat) (i : Nat) (h : i < a.size) :=
a[i] + a[i]
```
The bracket operator is whitespace sensitive.
```lean
def f (xs : List Nat) : List Nat :=
xs ++ xs
@@ -56,7 +57,21 @@ def f (xs : List Nat) : List Nat :=
def as : Array Nat :=
#[1, 2, 3, 4]
def idx : Fin 4 :=
2
#eval f [1, 2, 3] -- This is a function application
#eval as[2] -- This is an array access
#eval as[idx] -- This is an array access
```
The notation `a[i]` has two variants: `a[i]!` and `a[i]?`. In both cases, `i` has type `Nat`. The first one
produces a panic error message if the index `i` is out of bounds. The latter returns an `Option` type.
```lean
#eval #['a', 'b', 'c'][1]?
-- some 'b'
#eval #['a', 'b', 'c'][5]?
-- none
#eval #['a', 'b', 'c'][1]!
-- 'b!
```

View File

@@ -36,9 +36,9 @@ Note that, Lean inferred a more general type using `Sort` instead of `Type`.
Although we love this feature and use it extensively when implementing Lean,
we realize some users may feel uncomfortable with it. Thus, you can disable it using
the command `set_option autoBoundImplicitLocal false`.
the command `set_option autoImplicit false`.
```lean
set_option autoBoundImplicitLocal false
set_option autoImplicit false
/- The following definition produces `unknown identifier` errors -/
-- def compose (g : β → γ) (f : α → β) (x : α) : γ :=
-- g (f x)

View File

@@ -10,6 +10,12 @@ build-dir = "out"
[output.html]
git-repository-url = "https://github.com/leanprover/lean4"
additional-css = ["alectryon.css", "pygments.css"]
additional-js = ["alectryon.js"]
[output.html.fold]
enable = true
level = 0
[output.html.playground.boring-prefixes]
lean = "# "

View File

@@ -74,7 +74,7 @@ Lean provides ways of adding new objects to the environment. The following provi
* ``axiom c : α`` : declare a constant named ``c`` of type ``α``, it is postulating that `α` is not an empty type.
* ``def c : α := v`` : defines ``c`` to denote ``v``, which should have type ``α``.
* ``theorem c : p := v`` : similar to ``def``, but intended to be used when ``p`` is a proposition.
* ``constant c : α (:= v)?`` : declares a opaque constant named ``c`` of type ``α``, the optional value `v` is must have type `α`
* ``opaque c : α (:= v)?`` : declares a opaque constant named ``c`` of type ``α``, the optional value `v` is must have type `α`
and can be viewed as a certificate that ``α`` is not an empty type. If the value is not provided, Lean tries to find one
using a proceture based on type class resolution. The value `v` is hidden from the type checker. You can assume that
Lean "forgets" `v` after type checking this kind of declaration.
@@ -89,8 +89,8 @@ Any of ``def``, ``theorem``, ``axiom``, or ``example`` can take a list of argume
is interpreted as ``def foo : (a : α) → β := fun a : α => t``. Similarly, a theorem ``theorem foo (a : α) : p := t`` is interpreted as ``theorem foo : ∀ a : α, p := fun a : α => t``.
```lean
constant c : Nat
constant d : Nat
opaque c : Nat
opaque d : Nat
axiom cd_eq : c = d
def foo : Nat := 5
@@ -165,70 +165,70 @@ Below are some common examples of inductive types, many of which are defined in
.. code-block:: lean
namespace hide
universes u v
namespace Hide
universe u v
-- BEGIN
inductive empty : Type
inductive Empty : Type
inductive unit : Type
| star : unit
inductive Unit : Type
| unit : Unit
inductive bool : Type
| ff : bool
| tt : bool
inductive Bool : Type
| false : Bool
| true : Bool
inductive prod (α : Type u) (β : Type v) : Type (max u v)
| mk : α → β → prod
inductive Prod (α : Type u) (β : Type v) : Type (max u v)
| mk : α → β → Prod α β
inductive sum (α : Type u) (β : Type v)
| inl : αsum
| inr : β → sum
inductive Sum (α : Type u) (β : Type v)
| inl : αSum α β
| inr : β → Sum α β
inductive sigma (α : Type u) (β : α → Type v)
| mk : Π a : α, β a → sigma
inductive Sigma (α : Type u) (β : α → Type v)
| mk : (a : α) → β a → Sigma α β
inductive false : Prop
inductive true : Prop
| trivial : true
inductive True : Prop
| trivial : True
inductive and (p q : Prop) : Prop
| intro : p → q → and
inductive And (p q : Prop) : Prop
| intro : p → q → And p q
inductive or (p q : Prop) : Prop
| inl : p → or
| inr : q → or
inductive Or (p q : Prop) : Prop
| inl : p → Or p q
| inr : q → Or p q
inductive Exists (α : Type u) (p : α → Prop) : Prop
| intro : ∀ x : α, p x → Exists
| intro : ∀ x : α, p x → Exists α p
inductive subtype (α : Type u) (p : α → Prop) : Type u
| intro : ∀ x : α, p x → subtype
inductive Subtype (α : Type u) (p : α → Prop) : Type u
| intro : ∀ x : α, p x → Subtype α p
inductive nat : Type
| zero : nat
| succ : nat → nat
inductive Nat : Type
| zero : Nat
| succ : Nat → Nat
inductive list (α : Type u)
| nil : list
| cons : αlist → list
inductive List (α : Type u)
| nil : List α
| cons : αList αList α
-- full binary tree with nodes and leaves labeled from α
inductive bintree (α : Type u)
| leaf : αbintree
| node : bintree → αbintree → bintree
inductive BinTree (α : Type u)
| leaf : αBinTree α
| node : BinTree ααBinTree αBinTree α
-- every internal node has subtrees indexed by Nat
inductive cbt (α : Type u)
| leaf : αcbt
| node : (Nat → cbt) → cbt
inductive CBT (α : Type u)
| leaf : αCBT α
| node : (Nat → CBT α) → CBT α
-- END
end hide
Note that in the syntax of the inductive definition ``foo``, the context ``(a : α)`` is left implicit. In other words, constructors and recursive arguments are written as though they have return type ``foo`` rather than ``foo a``.
Note that in the syntax of the inductive definition ``Foo``, the context ``(a : α)`` is left implicit. In other words, constructors and recursive arguments are written as though they have return type ``Foo`` rather than ``Foo a``.
Elements of the context ``(a : α)`` can be marked implicit as described in [Implicit Arguments](#implicit.md#implicit_arguments). These annotations bear only on the type former, ``foo``. Lean uses a heuristic to determine which arguments to the constructors should be marked implicit, namely, an argument is marked implicit if it can be inferred from the type of a subsequent argument. If the annotation ``{}`` appears after the constructor, a argument is marked implicit if it can be inferred from the type of a subsequent argument *or the return type*. For example, it is useful to let ``nil`` denote the empty list of any type, since the type can usually be inferred in the context in which it appears. These heuristics are imperfect, and you may sometimes wish to define your own constructors in terms of the default ones. In that case, use the ``[pattern]`` [attribute](TODO: missing link) to ensure that these will be used appropriately by the [Equation Compiler](#the-equation-compiler).
Elements of the context ``(a : α)`` can be marked implicit as described in [Implicit Arguments](#implicit.md#implicit_arguments). These annotations bear only on the type former, ``Foo``. Lean uses a heuristic to determine which arguments to the constructors should be marked implicit, namely, an argument is marked implicit if it can be inferred from the type of a subsequent argument. If the annotation ``{}`` appears after the constructor, a argument is marked implicit if it can be inferred from the type of a subsequent argument *or the return type*. For example, it is useful to let ``nil`` denote the empty list of any type, since the type can usually be inferred in the context in which it appears. These heuristics are imperfect, and you may sometimes wish to define your own constructors in terms of the default ones. In that case, use the ``[matchPattern]`` [attribute](TODO: missing link) to ensure that these will be used appropriately by the [Equation Compiler](#the-equation-compiler).
There are restrictions on the universe ``u`` in the return type ``Sort u`` of the type former. There are also restrictions on the universe ``u`` in the return type ``Sort u`` of the motive of the eliminator. These will be discussed in the next section in the more general setting of inductive families.
@@ -236,69 +236,69 @@ Lean allows some additional syntactic conveniences. You can omit the return type
.. code-block:: lean
namespace hide
namespace Hide
universe u
-- BEGIN
inductive weekday
inductive Weekday
| sunday | monday | tuesday | wednesday
| thursday | friday | saturday
inductive nat
inductive Nat
| zero
| succ (n : nat) : nat
| succ (n : Nat) : Nat
inductive list (α : Type u)
| nil {} : list
| cons (a : α) (l : list) : list
inductive List (α : Type u)
| nil : List α
| cons (a : α) (l : List α) : List α
@[pattern]
def list.nil' (α : Type u) : list α := list.nil
@[matchPattern]
def List.nil' (α : Type u) : List α := List.nil
def length {α : Type u} : list α → Nat
| (list.nil' .(α)) := 0
| (list.cons a l) := 1 + length l
def length {α : Type u} : List α → Nat
| (List.nil' _) => 0
| (List.cons a l) => 1 + length l
-- END
end hide
end Hide
The type former, constructors, and eliminator are all part of Lean's axiomatic foundation, which is to say, they are part of the trusted kernel. In addition to these axiomatically declared constants, Lean automatically defines some additional objects in terms of these, and adds them to the environment. These include the following:
- ``foo.rec_on`` : a variant of the eliminator, in which the major premise comes first
- ``foo.cases_on`` : a restricted version of the eliminator which omits any recursive calls
- ``foo.no_confusion_type``, ``foo.no_confusion`` : functions which witness the fact that the inductive type is freely generated, i.e. that the constructors are injective and that distinct constructors produce distinct objects
- ``foo.below``, ``foo.ibelow`` : functions used by the equation compiler to implement structural recursion
- ``foo.sizeof`` : a measure which can be used for well-founded recursion
- ``Foo.recOn`` : a variant of the eliminator, in which the major premise comes first
- ``Foo.casesOn`` : a restricted version of the eliminator which omits any recursive calls
- ``Foo.noConfusionType``, ``Foo.noConfusion`` : functions which witness the fact that the inductive type is freely generated, i.e. that the constructors are injective and that distinct constructors produce distinct objects
- ``Foo.below``, ``Foo.ibelow`` : functions used by the equation compiler to implement structural recursion
- ``instance : SizeOf Foo`` : a measure which can be used for well-founded recursion
Note that it is common to put definitions and theorems related to a datatype ``foo`` in a namespace of the same name. This makes it possible to use projection notation described in [Structures](struct.md#structures) and [Namespaces](namespaces.md#namespaces).
.. code-block:: lean
namespace hide
namespace Hide
universe u
-- BEGIN
inductive nat
inductive Nat
| zero
| succ (n : nat) : nat
| succ (n : Nat) : Nat
#check nat
#check nat.rec
#check nat.zero
#check nat.succ
#check Nat
#check @Nat.rec
#check Nat.zero
#check Nat.succ
#check nat.rec_on
#check nat.cases_on
#check nat.no_confusion_type
#check @nat.no_confusion
#check nat.brec_on
#check nat.below
#check nat.ibelow
#check nat.sizeof
#check @Nat.recOn
#check @Nat.casesOn
#check @Nat.noConfusionType
#check @Nat.noConfusion
#check @Nat.brecOn
#check Nat.below
#check Nat.ibelow
#check Nat._sizeOf_1
-- END
end hide
end Hide
.. _inductive_families:
@@ -309,39 +309,39 @@ In fact, Lean implements a slight generalization of the inductive types describe
.. code-block:: text
inductive foo (a : α) : Π (c : γ), Sort u
| constructor₁ : Π (b : β₁), foo t₁
| constructor₂ : Π (b : β₂), foo t₂
inductive Foo (a : α) : Π (c : γ), Sort u
| constructor₁ : Π (b : β₁), Foo t₁
| constructor₂ : Π (b : β₂), Foo t₂
...
| constructorₙ : Π (b : βₙ), foo tₙ
| constructorₙ : Π (b : βₙ), Foo tₙ
Here ``(a : α)`` is a context, ``(c : γ)`` is a telescope in context ``(a : α)``, each ``(b : βᵢ)`` is a telescope in the context ``(a : α)`` together with ``(foo : Π (c : γ), Sort u)`` subject to the constraints below, and each ``tᵢ`` is a tuple of terms in the context ``(a : α) (b : βᵢ)`` having the types ``γ``. Instead of defining a single inductive type ``foo a``, we are now defining a family of types ``foo a c`` indexed by elements ``c : γ``. Each constructor, ``constructorᵢ``, places its result in the type ``foo a tᵢ``, the member of the family with index ``tᵢ``.
Here ``(a : α)`` is a context, ``(c : γ)`` is a telescope in context ``(a : α)``, each ``(b : βᵢ)`` is a telescope in the context ``(a : α)`` together with ``(Foo : Π (c : γ), Sort u)`` subject to the constraints below, and each ``tᵢ`` is a tuple of terms in the context ``(a : α) (b : βᵢ)`` having the types ``γ``. Instead of defining a single inductive type ``Foo a``, we are now defining a family of types ``Foo a c`` indexed by elements ``c : γ``. Each constructor, ``constructorᵢ``, places its result in the type ``Foo a tᵢ``, the member of the family with index ``tᵢ``.
The modifications to the scheme in the previous section are straightforward. Suppose the telescope ``(b : βᵢ)`` is ``(b₁ : βᵢ₁) ... (bᵤ : βᵢᵤ)``.
- As before, an argument ``(bⱼ : βᵢⱼ)`` is *nonrecursive* if ``βᵢⱼ`` does not refer to ``foo,`` the inductive type being defined. In that case, ``βᵢⱼ`` can be any type, so long as it does not refer to any nonrecursive arguments.
- As before, an argument ``(bⱼ : βᵢⱼ)`` is *nonrecursive* if ``βᵢⱼ`` does not refer to ``Foo,`` the inductive type being defined. In that case, ``βᵢⱼ`` can be any type, so long as it does not refer to any nonrecursive arguments.
- An argument ``(bⱼ : βᵢⱼ)`` is *recursive* if ``βᵢⱼ`` is of the form ``Π (d : δ), foo s`` where ``(d : δ)`` is a telescope which does not refer to ``foo`` or any nonrecursive arguments and ``s`` is a tuple of terms in context ``(a : α)`` and the previous nonrecursive ``bⱼ``'s with types ``γ``.
- An argument ``(bⱼ : βᵢⱼ)`` is *recursive* if ``βᵢⱼ`` is of the form ``Π (d : δ), Foo s`` where ``(d : δ)`` is a telescope which does not refer to ``Foo`` or any nonrecursive arguments and ``s`` is a tuple of terms in context ``(a : α)`` and the previous nonrecursive ``bⱼ``'s with types ``γ``.
The declaration of the type ``foo`` as above results in the addition of the following constants to the environment:
The declaration of the type ``Foo`` as above results in the addition of the following constants to the environment:
- the *type former* ``foo : Π (a : α) (c : γ), Sort u``
- for each ``i``, the *constructor* ``foo.constructorᵢ : Π (a : α) (b : βᵢ), foo a tᵢ``
- the *eliminator* ``foo.rec``, which takes arguments
- the *type former* ``Foo : Π (a : α) (c : γ), Sort u``
- for each ``i``, the *constructor* ``Foo.constructorᵢ : Π (a : α) (b : βᵢ), Foo a tᵢ``
- the *eliminator* ``Foo.rec``, which takes arguments
+ ``(a : α)`` (the parameters)
+ ``{C : Π (c : γ), foo a c → Type u}`` (the motive of the elimination)
+ ``{C : Π (c : γ), Foo a c → Type u}`` (the motive of the elimination)
+ for each ``i``, the minor premise corresponding to ``constructorᵢ``
+ ``(x : foo a)`` (the major premise)
+ ``(x : Foo a)`` (the major premise)
and returns an element of ``C x``. Here, The ith minor premise is a function which takes
+ ``(b : βᵢ)`` (the arguments to the constructor)
+ an argument of type ``Π (d : δ), C s (bⱼ d)`` corresponding to each recursive argument ``(bⱼ : βᵢⱼ)``, where ``βᵢⱼ`` is of the form ``Π (d : δ), foo s``
+ an argument of type ``Π (d : δ), C s (bⱼ d)`` corresponding to each recursive argument ``(bⱼ : βᵢⱼ)``, where ``βᵢⱼ`` is of the form ``Π (d : δ), Foo s``
and returns an element of ``C tᵢ (constructorᵢ a b)``.
Suppose we set ``F := foo.rec a C f₁ ... fₙ``. Then for each constructor, we have the definitional reduction, as before:
Suppose we set ``F := Foo.rec a C f₁ ... fₙ``. Then for each constructor, we have the definitional reduction, as before:
.. code-block :: text
@@ -353,24 +353,24 @@ The following are examples of inductive families.
.. code-block:: lean
namespace hide
namespace Hide
universe u
-- BEGIN
inductive vector (α : Type u) : Nat → Type u
| nil : vector 0
| succ : Π n, vector n → vector (n + 1)
inductive Vector (α : Type u) : Nat → Type u
| nil : Vector 0
| succ : Π n, Vector n → Vector (n + 1)
-- 'is_prod s n' means n is a product of elements of s
inductive is_prod (s : set Nat) : Nat → Prop
| base : ∀ n ∈ s, is_prod n
| step : ∀ m n, is_prod m → is_prod n → is_prod (m * n)
-- 'IsProd s n' means n is a product of elements of s
inductive IsProd (s : Set Nat) : Nat → Prop
| base : ∀ n ∈ s, IsProd n
| step : ∀ m n, IsProd m → IsProd n → IsProd (m * n)
inductive eq {α : Sort u} (a : α) : α → Prop
| refl : eq a
inductive Eq {α : Sort u} (a : α) : α → Prop
| refl : Eq a
-- END
end hide
end Hide
We can now describe the constraints on the return type of the type former, ``Sort u``. We can always take ``u`` to be ``0``, in which case we are defining an inductive family of propositions. If ``u`` is nonzero, however, it must satisfy the following constraint: for each type ``βᵢⱼ : Sort v`` occurring in the constructors, we must have ``u ≥ v``. In the set-theoretic interpretation, this ensures that the universe in which the resulting type resides is large enough to contain the inductively generated family, given the number of distinctly-labeled constructors. The restriction does not hold for inductively defined propositions, since these contain no data.
@@ -387,42 +387,47 @@ The first generalization allows for multiple inductive types to be defined simul
.. code-block:: text
mutual inductive foo, bar (a : α)
with foo : Π (c : γ), Sort u
| constructor₁₁ : Π (b : β₁₁), foo t₁₁
| constructor₁ : Π (b : β₁), foo t₁
mutual
inductive Foo (a : α) : Π (c : γ₁), Sort u
| constructor₁ : Π (b : β₁), Foo a t₁
| constructor₁₂ : Π (b : β₁₂), Foo a t₁₂
...
| constructor₁ₙ : Π (b : β₁ₙ), foo t₁ₙ
with bar :
| constructor₂₁ : Π (b : β₂₁), bar t₂₁
| constructor₂ : Π (b : β₂), bar t₂
| constructor₁ₙ : Π (b : β₁ₙ), Foo a t₁ₙ
inductive Bar (a : α) : Π (c : γ₂), Sort u
| constructor₂ : Π (b : β₂), Bar a t₂
| constructor₂₂ : Π (b : β₂₂), Bar a t₂₂
...
| constructor₂ₘ : Π (b : β₂ₘ), bar t₂ₘ
| constructor₂ₘ : Π (b : β₂ₘ), Bar a t₂ₘ
Here the syntax is shown for defining two inductive families, ``foo`` and ``bar``, but any number is allowed. The restrictions are almost the same as for ordinary inductive families. For example, each ``(b : βᵢⱼ)`` is a telescope relative to the context ``(a : α)``. The difference is that the constructors can now have recursive arguments whose return types are any of the inductive families currently being defined, in this case ``foo`` and ``bar``. Note that all of the inductive definitions share the same parameters ``(a : α)``, though they may have different indices.
end
A mutual inductive definition is compiled down to an ordinary inductive definition using an extra finite-valued index to distinguish the components. The details of the internal construction are meant to be hidden from most users. Lean defines the expected type formers ``foo`` and ``bar`` and constructors ``constructorᵢⱼ`` from the internal inductive definition. There is no straightforward elimination principle, however. Instead, Lean defines an appropriate ``sizeof`` measure, meant for use with well-founded recursion, with the property that the recursive arguments to a constructor are smaller than the constructed value.
Here the syntax is shown for defining two inductive families, ``Foo`` and ``Bar``, but any number is allowed. The restrictions are almost the same as for ordinary inductive families. For example, each ``(b : βᵢⱼ)`` is a telescope relative to the context ``(a : α)``. The difference is that the constructors can now have recursive arguments whose return types are any of the inductive families currently being defined, in this case ``Foo`` and ``Bar``. Note that all of the inductive definitions share the same parameters ``(a : α)``, though they may have different indices.
The second generalization relaxes the restriction that in the recursive definition of ``foo``, ``foo`` can only occur strictly positively in the type of any of its recursive arguments. Specifically, in a nested inductive definition, ``foo`` can appear as an argument to another inductive type constructor, so long as the corresponding parameter occurs strictly positively in the constructors for *that* inductive type. This process can be iterated, so that additional type constructors can be applied to those, and so on.
A mutual inductive definition is compiled down to an ordinary inductive definition using an extra finite-valued index to distinguish the components. The details of the internal construction are meant to be hidden from most users. Lean defines the expected type formers ``Foo`` and ``Bar`` and constructors ``constructorᵢⱼ`` from the internal inductive definition. There is no straightforward elimination principle, however. Instead, Lean defines an appropriate ``sizeOf`` measure, meant for use with well-founded recursion, with the property that the recursive arguments to a constructor are smaller than the constructed value.
A nested inductive definition is compiled down to an ordinary inductive definition using a mutual inductive definition to define copies of all the nested types simultaneously. Lean then constructs isomorphisms between the mutually defined nested types and their independently defined counterparts. Once again, the internal details are not meant to be manipulated by users. Rather, the type former and constructors are made available and work as expected, while an appropriate ``sizeof`` measure is generated for use with well-founded recursion.
The second generalization relaxes the restriction that in the recursive definition of ``Foo``, ``Foo`` can only occur strictly positively in the type of any of its recursive arguments. Specifically, in a nested inductive definition, ``Foo`` can appear as an argument to another inductive type constructor, so long as the corresponding parameter occurs strictly positively in the constructors for *that* inductive type. This process can be iterated, so that additional type constructors can be applied to those, and so on.
A nested inductive definition is compiled down to an ordinary inductive definition using a mutual inductive definition to define copies of all the nested types simultaneously. Lean then constructs isomorphisms between the mutually defined nested types and their independently defined counterparts. Once again, the internal details are not meant to be manipulated by users. Rather, the type former and constructors are made available and work as expected, while an appropriate ``sizeOf`` measure is generated for use with well-founded recursion.
.. code-block:: lean
universe u
-- BEGIN
mutual inductive even, odd
with even : Nat → Prop
| even_zero : even 0
| even_succ : ∀ n, odd n → even (n + 1)
with odd : Nat → Prop
| odd_succ : ∀ n, even n → odd (n + 1)
mutual
inductive Even : Nat → Prop
| even_zero : Even 0
| even_succ : ∀ n, Odd n → Even (n + 1)
inductive Odd : Nat → Prop
| odd_succ : ∀ n, Even n → Odd (n + 1)
end
inductive tree (α : Type u)
| mk : αlist tree → tree
inductive Tree (α : Type u)
| mk : αList (Tree α)Tree α
inductive double_tree (α : Type u)
| mk : αlist double_tree × list double_tree → double_tree
inductive DoubleTree (α : Type u)
| mk : αList (DoubleTree α) × List (DoubleTree α)DoubleTree α
-- END
.. _the_equation_compiler:
@@ -435,9 +440,9 @@ The equation compiler takes an equational description of a function or proof and
.. code-block:: text
def foo (a : α) : Π (b : β), γ
| [patterns₁] := t₁
| [patterns₁] => t₁
...
| [patternsₙ] := tₙ
| [patternsₙ] => tₙ
Here ``(a : α)`` is a telescope, ``(b : β)`` is a telescope in the context ``(a : α)``, and ``γ`` is an expression in the context ``(a : α) (b : β)`` denoting a ``Type`` or a ``Prop``.
@@ -450,78 +455,78 @@ Each ``patternsᵢ`` is a sequence of patterns of the same length as ``(b : β)`
In the last case, the pattern must be enclosed in parentheses.
Each term ``tᵢ`` is an expression in the context ``(a : α)`` together with the variables introduced on the left-hand side of the token ``:=``. The term ``tᵢ`` can also include recursive calls to ``foo``, as described below. The equation compiler does case splitting on the variables ``(b : β)`` as necessary to match the patterns, and defines ``foo`` so that it has the value ``tᵢ`` in each of the cases. In ideal circumstances (see below), the equations hold definitionally. Whether they hold definitionally or only propositionally, the equation compiler proves the relevant equations and assigns them internal names. They are accessible by the ``rewrite`` and ``simp`` tactics under the name ``foo`` (see [Rewrite](tactics.md#rewrite) and _[TODO: where is simplifier tactic documented?]_. If some of the patterns overlap, the equation compiler interprets the definition so that the first matching pattern applies in each case. Thus, if the last pattern is a variable, it covers all the remaining cases. If the patterns that are presented do not cover all possible cases, the equation compiler raises an error.
Each term ``tᵢ`` is an expression in the context ``(a : α)`` together with the variables introduced on the left-hand side of the token ``=>``. The term ``tᵢ`` can also include recursive calls to ``foo``, as described below. The equation compiler does case splitting on the variables ``(b : β)`` as necessary to match the patterns, and defines ``foo`` so that it has the value ``tᵢ`` in each of the cases. In ideal circumstances (see below), the equations hold definitionally. Whether they hold definitionally or only propositionally, the equation compiler proves the relevant equations and assigns them internal names. They are accessible by the ``rewrite`` and ``simp`` tactics under the name ``foo`` (see [Rewrite](tactics.md#rewrite) and _[TODO: where is simplifier tactic documented?]_. If some of the patterns overlap, the equation compiler interprets the definition so that the first matching pattern applies in each case. Thus, if the last pattern is a variable, it covers all the remaining cases. If the patterns that are presented do not cover all possible cases, the equation compiler raises an error.
When identifiers are marked with the ``[pattern]`` attribute, the equation compiler unfolds them in the hopes of exposing a constructor. For example, this makes it possible to write ``n+1`` and ``0`` instead of ``nat.succ n`` and ``nat.zero`` in patterns.
When identifiers are marked with the ``[matchPattern]`` attribute, the equation compiler unfolds them in the hopes of exposing a constructor. For example, this makes it possible to write ``n+1`` and ``0`` instead of ``Nat.succ n`` and ``Nat.zero`` in patterns.
For a nonrecursive definition involving case splits, the defining equations will hold definitionally. With inductive types like ``char``, ``string``, and ``fin n``, a case split would produce definitions with an inordinate number of cases. To avoid this, the equation compiler uses ``if ... then ... else`` instead of ``cases_on`` when defining the function. In this case, the defining equations hold definitionally as well.
For a nonrecursive definition involving case splits, the defining equations will hold definitionally. With inductive types like ``Char``, ``String``, and ``Fin n``, a case split would produce definitions with an inordinate number of cases. To avoid this, the equation compiler uses ``if ... then ... else`` instead of ``casesOn`` when defining the function. In this case, the defining equations hold definitionally as well.
.. code-block:: lean
open nat
open Nat
def sub2 : Nat → Nat
| zero := 0
| (succ zero) := 0
| (succ (succ a)) := a
| zero => 0
| succ zero => 0
| succ (succ a) => a
def bar : Nat → list Nat → bool → Nat
| 0 _ ff := 0
| 0 (b :: _) _ := b
| 0 [] tt := 7
| (a+1) [] ff := a
| (a+1) [] tt := a + 1
| (a+1) (b :: _) _ := a + b
def bar : Nat → List Nat → Bool → Nat
| 0, _, false => 0
| 0, b :: _, _ => b
| 0, [], true => 7
| a+1, [], false => a
| a+1, [], true => a + 1
| a+1, b :: _, _ => a + b
def baz : char → Nat
| 'A' := 1
| 'B' := 2
| _ := 3
def baz : Char → Nat
| 'A' => 1
| 'B' => 2
| _ => 3
If any of the terms ``tᵢ`` in the template above contain a recursive call to ``foo``, the equation compiler tries to interpret the definition as a structural recursion. In order for that to succeed, the recursive arguments must be subterms of the corresponding arguments on the left-hand side. The function is then defined using a *course of values* recursion, using automatically generated functions ``below`` and ``brec`` in the namespace corresponding to the inductive type of the recursive argument. In this case the defining equations hold definitionally, possibly with additional case splits.
.. code-block:: lean
namespace hide
namespace Hide
-- BEGIN
def fib : nat → nat
| 0 := 1
| 1 := 1
| (n+2) := fib (n+1) + fib n
def fib : Nat → Nat
| 0 => 1
| 1 => 1
| (n+2) => fib (n+1) + fib n
def append {α : Type} : list αlist αlist α
| [] l := l
| (h::t) l := h :: append t l
def append {α : Type} : List αList αList α
| [], l => l
| h::t, l => h :: append t l
example : append [(1 : Nat), 2, 3] [4, 5] = [1, 2, 3, 4, 5] := rfl
example : append [(1 : Nat), 2, 3] [4, 5] = [1, 2, 3, 4, 5] => rfl
-- END
end hide
end Hide
If structural recursion fails, the equation compiler falls back on well-founded recursion. It tries to infer an instance of ``has_sizeof`` for the type of each argument, and then show that each recursive call is decreasing under the lexicographic order of the arguments with respect to ``sizeof`` measure. If it fails, the error message provides information as to the goal that Lean tried to prove. Lean uses information in the local context, so you can often provide the relevant proof manually using ``have`` in the body of the definition. In this case of well-founded recursion, the defining equations hold only propositionally, and can be accessed using ``simp`` and ``rewrite`` with the name ``foo``.
If structural recursion fails, the equation compiler falls back on well-founded recursion. It tries to infer an instance of ``SizeOf`` for the type of each argument, and then show that each recursive call is decreasing under the lexicographic order of the arguments with respect to ``sizeOf`` measure. If it fails, the error message provides information as to the goal that Lean tried to prove. Lean uses information in the local context, so you can often provide the relevant proof manually using ``have`` in the body of the definition. In this case of well-founded recursion, the defining equations hold only propositionally, and can be accessed using ``simp`` and ``rewrite`` with the name ``foo``.
.. code-block:: lean
namespace hide
open nat
namespace Hide
open Nat
-- BEGIN
def div : Nat → Nat → Nat
| x y :=
| x, y =>
if h : 0 < y ∧ y ≤ x then
have x - y < x,
from sub_lt (lt_of_lt_of_le h.left h.right) h.left,
have : x - y < x :=
sub_lt (Nat.lt_of_lt_of_le h.left h.right) h.left
div (x - y) y + 1
else
0
example (x y : Nat) :
div x y = if 0 < y ∧ y ≤ x then div (x - y) y + 1 else 0 :=
by rw [div]
by rw [div]; rfl
-- END
end hide
end Hide
Note that recursive definitions can in general require nested recursions, that is, recursion on different arguments of ``foo`` in the template above. The equation compiler handles this by abstracting later arguments, and recursively defining higher-order functions to meet the specification.
@@ -529,13 +534,14 @@ The equation compiler also allows mutual recursive definitions, with a syntax si
.. code-block:: lean
mutual def even, odd
with even : Nat → bool
| 0 := tt
| (a+1) := odd a
with odd : Nat → bool
| 0 := ff
| (a+1) := even a
mutual
def even : Nat → Bool
| 0 => true
| a+1 => odd a
def odd : Nat → Bool
| 0 => false
| a+1 => even a
end
example (a : Nat) : even (a + 1) = odd a :=
by simp [even]
@@ -547,36 +553,39 @@ Well-founded recursion is especially useful with [Mutual and Nested Inductive De
.. code-block:: lean
mutual inductive even, odd
with even : Nat → Prop
| even_zero : even 0
| even_succ : ∀ n, odd n → even (n + 1)
with odd : Nat → Prop
| odd_succ : ∀ n, even n → odd (n + 1)
mutual
inductive Even : Nat → Prop
| even_zero : Even 0
| even_succ : ∀ n, Odd n → Even (n + 1)
inductive Odd : Nat → Prop
| odd_succ : ∀ n, Even n → Odd (n + 1)
end
open even odd
open Even Odd
theorem not_odd_zero : ¬ odd 0.
theorem not_odd_zero : ¬ Odd 0 := fun x => nomatch x
mutual theorem even_of_odd_succ, odd_of_even_succ
with even_of_odd_succ : ∀ n, odd (n + 1) → even n
| _ (odd_succ n h) := h
with odd_of_even_succ : ∀ n, even (n + 1) → odd n
| _ (even_succ n h) := h
mutual
theorem even_of_odd_succ : ∀ n, Odd (n + 1) → Even n
| _, odd_succ n h => h
theorem odd_of_even_succ : ∀ n, Even (n + 1) → Odd n
| _, even_succ n h => h
end
inductive term
| const : string → term
| app : string → list term → term
inductive Term
| const : String → Term
| app : String → List Term → Term
open term
open Term
mutual def num_consts, num_consts_lst
with num_consts : term → nat
| (term.const n) := 1
| (term.app n ts) := num_consts_lst ts
with num_consts_lst : list term → nat
| [] := 0
| (t::ts) := num_consts t + num_consts_lst ts
mutual
def num_consts : Term → Nat
| .const n => 1
| .app n ts => num_consts_lst ts
def num_consts_lst : List Term → Nat
| [] => 0
| t::ts => num_consts t + num_consts_lst ts
end
The case where patterns are matched against an argument whose type is an inductive family is known as *dependent pattern matching*. This is more complicated, because the type of the function being defined can impose constraints on the patterns that are matched. In this case, the equation compiler will detect inconsistent cases and rule them out.
@@ -584,52 +593,24 @@ The case where patterns are matched against an argument whose type is an inducti
universe u
inductive vector (α : Type u) : Nat → Type u
| nil {} : vector 0
| cons : Π {n}, αvector n → vector (n+1)
inductive Vector (α : Type u) : Nat → Type u
| nil : Vector α 0
| cons : αVector α n → Vector α (n+1)
namespace vector
namespace Vector
def head {α : Type} : Π {n}, vector α (n+1) → α
| n (cons h t) := h
def head {α : Type} : Vector α (n+1) → α
| cons h t => h
def tail {α : Type} : Π {n}, vector α (n+1) → vector α n
| n (cons h t) := t
def tail {α : Type} : Vector α (n+1) → Vector α n
| cons h t => t
def map {α β γ : Type} (f : α → β → γ) :
Π {n}, vector α n → vector β n → vector γ n
| 0 nil nil := nil
| (n+1) (cons a va) (cons b vb) := cons (f a b) (map va vb)
{n}, Vector α n → Vector β n → Vector γ n
| 0, nil, nil => nil
| n+1, cons a va, cons b vb => cons (f a b) (map f va vb)
end vector
An expression of the form ``.(t)`` in a pattern is known as an *inaccessible term*. It is not viewed as part of the pattern; rather, it is explicit information that is used by the elaborator and equation compiler when interpreting the definition. Inaccessible terms do not participate in pattern matching. They are sometimes needed for a pattern to make sense, for example, when a constructor depends on a parameter that is not a pattern-matching variable. In other cases, they can be used to inform the equation compiler that certain arguments do not require a case split, and they can be used to make a definition more readable.
.. code-block:: lean
universe u
inductive vector (α : Type u) : Nat → Type u
| nil {} : vector 0
| cons : Π {n}, α → vector n → vector (n+1)
namespace vector
-- BEGIN
variable {α : Type u}
def add [has_add α] :
Π {n : Nat}, vector α n → vector α n → vector α n
| ._ nil nil := nil
| ._ (cons a v) (cons b w) := cons (a + b) (add v w)
def add' [has_add α] :
Π {n : Nat}, vector α n → vector α n → vector α n
| .(0) nil nil := nil
| .(n+1) (@cons .(α) n a v) (cons b w) := cons (a + b) (add' v w)
-- END
end vector
end Vector
.. _match_expressions:
@@ -641,9 +622,9 @@ Lean supports a ``match ... with ...`` construct similar to ones found in most f
.. code-block:: text
match t₁, ..., tₙ with
| p₁₁, ..., p₁ₙ := s₁
| p₁₁, ..., p₁ₙ => s₁
...
| pₘ₁, ..., pₘₙ := sₘ
| pₘ₁, ..., pₘₙ => sₘ
Here ``t₁, ..., tₙ`` are any terms in the context in which the expression appears, the expressions ``pᵢⱼ`` are patterns, and the terms ``sᵢ`` are expressions in the local context together with variables introduced by the patterns on the left-hand side. Each ``sᵢ`` should have the expected type of the entire ``match`` expression.
@@ -651,29 +632,42 @@ Any ``match`` expression is interpreted using the equation compiler, which gener
.. code-block:: lean
def foo (n : Nat) (b c : bool) :=
def foo (n : Nat) (b c : Bool) :=
5 + match n - 5, b && c with
| 0, tt := 0
| m+1, tt := m + 7
| 0, ff := 5
| m+1, ff := m + 3
end
| 0, true => 0
| m+1, true => m + 7
| 0, false => 5
| m+1, false => m + 3
When a ``match`` has only one line, the vertical bar may be left out. In that case, Lean provides alternative syntax with a destructuring ``let``, as well as a destructuring lambda abstraction. Thus the following definitions all have the same net effect.
When a ``match`` has only one line, Lean provides alternative syntax with a destructuring ``let``, as well as a destructuring lambda abstraction. Thus the following definitions all have the same net effect.
.. code-block:: lean
def bar₁ : Nat × Nat → Nat
| (m, n) := m + n
| (m, n) => m + n
def bar₂ (p : Nat × Nat) : Nat :=
match p with (m, n) := m + n end
match p with | (m, n) => m + n
def bar₃ : Nat × Nat → Nat :=
fun ⟨m, n⟩ => m + n
def bar₄ (p : Nat × Nat) : Nat :=
let ⟨m, n⟩ := p in m + n
let ⟨m, n⟩ := p; m + n
Information about the term being matched can be preserved in each branch using the syntax `match h : t with`. For example, a user may want to match a term `ns ++ ms : List Nat`, while tracking the hypothesis `ns ++ ms = []` or `ns ++ ms= h :: t` in the respective match arm:
```lean
def foo (ns ms : List Nat) (h1 : ns ++ ms ≠ []) (k : Nat -> Char) : Char :=
match h2 : ns ++ ms with
-- in this arm, we have the hypothesis `h2 : ns ++ ms = []`
| [] => absurd h2 h1
-- in this arm, we have the hypothesis `h2 : ns ++ ms = h :: t`
| h :: t => k h
-- '7'
#eval foo [7, 8, 9] [] (by decide) Nat.digitChar
```
.. _structures_and_records:
@@ -684,114 +678,113 @@ The ``structure`` command in Lean is used to define an inductive data type with
.. code-block:: text
structure foo (a : α) extends bar, baz : Sort u :=
structure Foo (a : α) extends Bar, Baz : Sort u :=
constructor :: (field₁ : β₁) ... (fieldₙ : βₙ)
Here ``(a : α)`` is a telescope, that is, the parameters to the inductive definition. The name ``constructor`` followed by the double colon is optional; if it is not present, the name ``mk`` is used by default. The keyword ``extends`` followed by a list of previously defined structures is also optional; if it is present, an instance of each of these structures is included among the fields to ``foo,`` and the types ``βᵢ`` can refer to their fields as well. The output type, ``Sort u``, can be omitted, in which case Lean infers to smallest non-``Prop`` sort possible. Finally, ``(field₁ : β₁) ... (fieldₙ : βₙ)`` is a telescope relative to ``(a : α)`` and the fields in ``bar`` and ``baz``.
Here ``(a : α)`` is a telescope, that is, the parameters to the inductive definition. The name ``constructor`` followed by the double colon is optional; if it is not present, the name ``mk`` is used by default. The keyword ``extends`` followed by a list of previously defined structures is also optional; if it is present, an instance of each of these structures is included among the fields to ``Foo``, and the types ``βᵢ`` can refer to their fields as well. The output type, ``Sort u``, can be omitted, in which case Lean infers to smallest non-``Prop`` sort possible. Finally, ``(field₁ : β₁) ... (fieldₙ : βₙ)`` is a telescope relative to ``(a : α)`` and the fields in ``bar`` and ``baz``.
The declaration above is syntactic sugar for an inductive type declaration, and so results in the addition of the following constants to the environment:
- the type former : ``foo : Π (a : α), Sort u``
- the type former : ``Foo : Π (a : α), Sort u``
- the single constructor :
.. code-block:: text
foo.constructor : Π (a : α) (_to_foo : foo) (_to_bar : bar)
(field₁ : β₁) ... (fieldₙ : βₙ), foo a
Foo.constructor : Π (a : α) (toBar : Bar) (toBaz : Baz)
(field₁ : β₁) ... (fieldₙ : βₙ), Foo a
- the eliminator ``foo.rec`` for the inductive type with that constructor
- the eliminator ``Foo.rec`` for the inductive type with that constructor
In addition, Lean defines
- the projections : ``fieldᵢ : Π (a : α) (c : foo) : βᵢ`` for each ``i``
- the projections : ``fieldᵢ : Π (a : α) (c : Foo) : βᵢ`` for each ``i``
where any other fields mentioned in ``βᵢ`` are replaced by the relevant projections from ``c``.
Given ``c : foo``, Lean offers the following convenient syntax for the projection ``foo.fieldᵢ c``:
Given ``c : Foo``, Lean offers the following convenient syntax for the projection ``Foo.fieldᵢ c``:
- *anonymous projections* : ``c.fieldᵢ``
- *numbered projections* : ``c.i``
These can be used in any situation where Lean can infer that the type of ``c`` is of the form ``foo a``. The convention for anonymous projections is extended to any function ``f`` defined in the namespace ``foo``, as described in [Namespaces](namespaces.md).
These can be used in any situation where Lean can infer that the type of ``c`` is of the form ``Foo a``. The convention for anonymous projections is extended to any function ``f`` defined in the namespace ``Foo``, as described in [Namespaces](namespaces.md).
Similarly, Lean offers the following convenient syntax for constructing elements of ``foo``. They are equivalent to ``foo.constructor b₁ b₂ f₁ f₁ ... fₙ``, where ``b₁ : foo``, ``b₂ : bar``, and each ``fᵢ : βᵢ`` :
Similarly, Lean offers the following convenient syntax for constructing elements of ``Foo``. They are equivalent to ``Foo.constructor b₁ b₂ f₁ f₁ ... fₙ``, where ``b₁ : Bar``, ``b₂ : Baz``, and each ``fᵢ : βᵢ`` :
- *anonymous constructor*: ``⟨ b₁, b₂, f₁, ..., fₙ ⟩``
- *record notation*:
.. code-block:: text
{ foo . to_bar := b₁, to_baz := b₂, field₁ := f₁, ...,
fieldₙ := fₙ }
{ toBar := b₁, toBaz := b₂, field₁ := f₁, ...,
fieldₙ := fₙ : Foo a }
The anonymous constructor can be used in any context where Lean can infer that the expression should have a type of the form ``foo a``. The unicode brackets are entered as ``\<`` and ``\>`` respectively. The tokens ``(|`` and ``|)`` are ascii equivalents.
The anonymous constructor can be used in any context where Lean can infer that the expression should have a type of the form ``Foo a``. The unicode brackets are entered as ``\<`` and ``\>`` respectively.
When using record notation, you can omit the annotation ``foo .`` when Lean can infer that the expression should have a type of the form ``foo a``. You can replace either ``to_bar`` or ``to_baz`` by assignments to *their* fields as well, essentially acting as though the fields of ``bar`` and ``baz`` are simply imported into ``foo``. Finally, record notation also supports
When using record notation, you can omit the annotation ``: Foo a`` when Lean can infer that the expression should have a type of the form ``Foo a``. You can replace either ``toBar`` or ``toBaz`` by assignments to *their* fields as well, essentially acting as though the fields of ``Bar`` and ``Baz`` are simply imported into ``Foo``. Finally, record notation also supports
- *record updates*: ``{ t with ... fieldᵢ := fᵢ ...}``
Here ``t`` is a term of type ``foo a`` for some ``a``. The notation instructs Lean to take values from ``t`` for any field assignment that is omitted from the list.
Here ``t`` is a term of type ``Foo a`` for some ``a``. The notation instructs Lean to take values from ``t`` for any field assignment that is omitted from the list.
Lean also allows you to specify a default value for any field in a structure by writing ``(fieldᵢ : βᵢ := t)``. Here ``t`` specifies the value to use when the field ``fieldᵢ`` is left unspecified in an instance of record notation.
.. code-block:: lean
universes u v
universe u v
structure vec (α : Type u) (n : Nat) :=
(l : list α) (h : l.length = n)
structure Vec (α : Type u) (n : Nat) :=
(l : List α) (h : l.length = n)
structure foo (α : Type u) (β : Nat → Type v) : Type (max u v) :=
structure Foo (α : Type u) (β : Nat → Type v) : Type (max u v) :=
(a : α) (n : Nat) (b : β n)
structure bar :=
structure Bar :=
(c : Nat := 8) (d : Nat)
structure baz extends foo Nat (vec Nat), bar :=
(v : vec Nat n)
structure Baz extends Foo Nat (Vec Nat), Bar :=
(v : Vec Nat n)
#check foo
#check @foo.mk
#check @foo.rec
#check Foo
#check @Foo.mk
#check @Foo.rec
#check foo.a
#check foo.n
#check foo.b
#check Foo.a
#check Foo.n
#check Foo.b
#check baz
#check @baz.mk
#check @baz.rec
#check Baz
#check @Baz.mk
#check @Baz.rec
#check baz.to_foo
#check baz.to_bar
#check baz.v
#check Baz.toFoo
#check Baz.toBar
#check Baz.v
def bzz := vec.mk [1, 2, 3] rfl
def bzz := Vec.mk [1, 2, 3] rfl
#check vec.l bzz
#check vec.h bzz
#check Vec.l bzz
#check Vec.h bzz
#check bzz.l
#check bzz.h
#check bzz.1
#check bzz.2
example : vec Nat 3 := vec.mk [1, 2, 3] rfl
example : vec Nat 3 := ⟨[1, 2, 3], rfl⟩
example : vec Nat 3 := (| [1, 2, 3], rfl |)
example : vec Nat 3 := { vec . l := [1, 2, 3], h := rfl }
example : vec Nat 3 := { l := [1, 2, 3], h := rfl }
example : Vec Nat 3 := Vec.mk [1, 2, 3] rfl
example : Vec Nat 3 := ⟨[1, 2, 3], rfl⟩
example : Vec Nat 3 := { l := [1, 2, 3], h := rfl : Vec Nat 3 }
example : Vec Nat 3 := { l := [1, 2, 3], h := rfl }
example : foo Nat (vec Nat) := ⟨1, 3, bzz⟩
example : Foo Nat (Vec Nat) := ⟨1, 3, bzz⟩
example : baz := ⟨⟨1, 3, bzz⟩, ⟨5, 7⟩, bzz⟩
example : baz := { a := 1, n := 3, b := bzz, c := 5, d := 7, v := bzz}
def fzz : foo Nat (vec Nat) := {a := 1, n := 3, b := bzz}
example : Baz := ⟨⟨1, 3, bzz⟩, ⟨5, 7⟩, bzz⟩
example : Baz := { a := 1, n := 3, b := bzz, c := 5, d := 7, v := bzz}
def fzz : Foo Nat (Vec Nat) := {a := 1, n := 3, b := bzz}
example : foo Nat (vec Nat) := { fzz with a := 7 }
example : baz := { fzz with c := 5, d := 7, v := bzz }
example : Foo Nat (Vec Nat) := { fzz with a := 7 }
example : Baz := { fzz with c := 5, d := 7, v := bzz }
example : bar := { c := 8, d := 9 }
example : bar := { d := 9 } -- uses the default value for c
example : Bar := { c := 8, d := 9 }
example : Bar := { d := 9 } -- uses the default value for c
.. _type_classes:

View File

@@ -1,4 +1,3 @@
# Lean Build Bootstrapping
Since version 4, Lean is a partially bootstrapped program: most parts of the
@@ -16,17 +15,18 @@ stage0/
bin/lean
stage1/
include/
config.h # config variables used to build `lean` such as use allocator
runtime/lean.h # runtime headers, used by extracted C code, uses `config.h`
config.h # config variables used to build `lean` such as used allocator
runtime/lean.h # runtime header, used by extracted C code, uses `config.h`
share/lean/
Makefile # used by `leanmake`
lean.mk # used by `leanmake`
lib/
lean/**/*.olean # the Lean library (incl. the compiler) compiled by the previous stage's `lean`
temp/**/*.{c,o} # the library extracted to C and compiled by `leanc`
libInit.a libStd.a libLean.a # static libraries of the Lean library
libInit.a libLean.a # static libraries of the Lean library
libleancpp.a # a static library of the C++ sources of Lean
libleanshared.so # a dynamic library including the static libraries above
bin/
lean # the Lean compiler & server linked together from the above libraries
lean # the Lean compiler & server, a small executable that calls directly into libleanshared.so
leanc # a wrapper around a C compiler supplying search paths etc
leanmake # a wrapper around `make` supplying the Makefile above
stage2/...
@@ -55,7 +55,7 @@ We are not aware of any "meta-meta" parts that influence more than two stages of
compilation, so stage 3 should always be identical to stage 2 and only exists as
a sanity check.
In summary, doing a standard build via `make` involves these steps:
In summary, doing a standard build via `make` internally involves these steps:
1. compile the `stage0/src` archived sources into `stage0/bin/lean`
1. use it to compile the current library (*including* your changes) into `stage1/lib`
@@ -119,4 +119,4 @@ affect later stages. This is an issue in two specific cases.
To modify either of these flags both for building and editing the stdlib, adjust
the code in `stage0/src/stdlib_flags.h`. The flags will automatically be reset
on the next `update-stage0` when the file is overwritten with the original
version in `src/`.
version in `src/`.

View File

@@ -1,155 +0,0 @@
[google-style]: https://google.github.io/styleguide/cppguide.html
[cpplint]: /src/cmake/Modules/cpplint.py
# Coding Style
The Lean project is moving away from using any C++ as more and more of
the compiler is being bootstrapped in Lean itself. But the remaining
C++ codebase is using modified version of [Google's C++ Style
Guide][google-style].
## [C++11](http://en.wikipedia.org/wiki/C%2B%2B11) features
Lean makes extensive use of new features in the C++ 11 standard.
Developers must be familiar with the standard to be able to understand
the code. Here are some of the features that are extensively used.
- Type inference (aka `auto` keyword).
- Initializer lists.
- Lambda functions and expressions.
- `nullptr` constant.
- Strongly typed enumerations.
- Right angle brackets with no space is now allowed in C++ 11.
- Thread local storage.
- Threading facilities.
- Tuple types.
- Smart pointers.
- When using ``std::list`` make sure to include the `std::`
qualifier so you do not accidentally use the ``lean::list`` type.
- When using ``std::copy`` make sure to include the `std::`
qualifier so you do not accidentally use the ``lean::copy`` type.
- Small and focused functions are preferred: foo(). Try not to
exceed 500 lines in a function, except in tests.
- Do **not** use the `#ifndef-#define-#endif` idiom for header files.
Instead use `#pragma once`.
- Write `type const & v` instead of `const type & v`.
- Use `const` extensively.
- Use the macro `lean_assert` for assertions. The macro `lean_assert`
is extensively used when writing unit tests.
## Naming
- Class, method, and function names are lower case
Use `_` for composite names. Example: `type_checker`.
- Class/struct fields should start with the prefix `m_`.
Example:
```c++
class point {
int m_x;
int m_y;
public:
...
};
```
## Namespaces
All code is in the `lean` namespace. Each frontend is stored in a
separate nested namespace. For example, the SMT 2.0 frontend is stored
in the `lean::smt` namespace.
Exception: some debugging functions are stored outside of the `lean`
namespace. These functions are called `print` and are meant to be used
when debugging Lean using `gdb`.
Do not use `using namespace` in a header file.
## Templates
Organize template source code using the approach described at http://www.codeproject.com/Articles/3515/How-To-Organize-Template-Source-Code
## Idioms
Use some popular C++ idioms:
- [Pimpl](http://c2.com/cgi/wiki?PimplIdiom)
- [RAII](http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization) Resource Acquisition Is Initialization
## Formatting
* Use 4 spaces for indentation.
* `if-then-else` curly brackets not always required. The following
forms are acceptable:
```c++
if (cond) {
...
} else {
...
}
```
and
```c++
if (cond)
statement1;
else
statement2;
```
In *exceptional cases*, we also use
```c++
if (cond) statement;
```
and
```c++
if (cond) statement1; else stament2;
```
* `if-then-else-if-else`
The following forms are acceptable:
```c++
if (cond) {
...
} else if (cond) {
...
} else {
...
}
```c++
and
```c++
if (cond)
statement1;
else if (cond)
statement2;
else
statement3;
```
* Format code using extra spaces to make code more readable. For example:
```c++
environment const & m_env;
cache m_cache;
normalizer m_normalizer;
volatile bool m_interrupted;
```
instead of:
```c++
environment const & m_env;
cache m_cache;
normalizer m_normalizer;
volatile bool m_interrupted;
```
* Spaces in expressions. Write `a == b` instead of `a==b`. Similarly,
we write `x < y + 1` instead of `x<y+1`.

View File

@@ -20,8 +20,9 @@ Notable trace classes:
* `Meta.isDefEq`: unification
* `interpreter`: full execution trace of the interpreter. Only available in debug builds.
In pure contexts or when execution is aborted before the messages are finally printed, one can instead use the term `dbg_trace "msg with {interpolations}"; val` (`;` can also be replaced by a newline), which will print the message directly to stderr before evaluating `val`. `dbgTraceVal val` can be used as a shorthand for `dbg_trace "{val}"; val`.
In pure contexts or when execution is aborted before the messages are finally printed, one can instead use the term `dbg_trace "msg with {interpolations}"; val` (`;` can also be replaced by a newline), which will print the message to stderr before evaluating `val`. `dbgTraceVal val` can be used as a shorthand for `dbg_trace "{val}"; val`.
Note that if the return value is not actually used, the trace code is silently dropped as well.
In the language server, stderr output is buffered and shown as messages after a command has been elaborated, unless the option `server.stderrAsMessages` is deactivated.
## Debuggers

View File

@@ -43,6 +43,7 @@ In the case of `@[extern]` all *irrelevant* types are removed first; see next se
* it is none of the types described above
* it is not marked `unsafe`
* it has a single constructor with a single parameter of *relevant* type
is represented by the representation of that parameter's type.
For example, `{ x : α // p }`, the `Subtype` structure of a value of type `α` and an irrelevant proof, is represented by the representation of `α`.
@@ -66,33 +67,45 @@ Return values and `@[export]` parameters are always owned at the moment.
## Initialization
When including Lean code as part of a larger program, modules must be *initialized* before accessing any of their declarations.
Module initialization entails
* initialization of all "constants" (nullary functions), including closed terms lifted out of other functions
* execution of all `[init]` functions
* execution of all `[builtinInit]` functions, if the `builtin` parameter of the module initializer has been set
The module initializer is automatically run with the `builtin` flag for executables compiled from Lean code and for "plugins" loaded with `lean --plugin`.
For all other modules imported by `lean`, the initializer is run without `builtin`.
Thus `[init]` functions are run iff their module is imported, regardless of whether they have native code available or not, while `[builtinInit]` functions are only run for native executable or plugins, regardless of whether their module is imported or not.
`lean` uses built-in initializers for e.g. registering basic parsers that should be available even without importing their module (which is necessary for bootstrapping).
The initializer for module `A.B` is called `initialize_A_B` and will automatically initialize any imported modules.
Module initializers are idempotent, but not thread-safe.
Module initializers are idempotent (when run with the same `builtin` flag), but not thread-safe.
Together with initialization of the Lean runtime, you should execute code like the following exactly once before accessing any Lean declarations:
```c
void lean_initialize_runtime_module();
void lean_initialize();
lean_object * initialize_A_B(lean_object *);
lean_object * initialize_C(lean_object *);
lean_object * initialize_A_B(uint8_t builtin, lean_object *);
lean_object * initialize_C(uint8_t builtin, lean_object *);
...
lean_initialize_runtime_module();
//lean_initialize(); // necessary if you (indirectly) access the `Lean` package
lean_object * res;
res = initialize_A_B(lean_io_mk_world());
// use same default as for Lean executables
uint8_t builtin = 1;
res = initialize_A_B(builtin, lean_io_mk_world());
if (lean_io_result_is_ok(res)) {
lean_dec_ref(res);
} else {
lean_io_result_show_error(res);
lean_dec(res);
return ...; // do not access Lean declarations if initialization failed
return ...; // do not access Lean declarations if initialization failed
}
res = initialize_C(lean_io_mk_world());
res = initialize_C(builtin, lean_io_mk_world());
if (lean_io_result_is_ok(res)) {
...
//lean_init_task_manager(); // necessary if you (indirectly) use `Task`
//lean_init_task_manager(); // necessary if you (indirectly) use `Task`
lean_io_mark_end_initialization();
```

View File

@@ -1,39 +0,0 @@
Fixing Tests
============
The test suite contains some tests that compare the produced output
with the expected output. For example, the directory `tests/lean`
contains files such as [`bad_class.lean`](../tests/lean/bad_class.lean) and
[`bad_class.lean.expected.out`](../tests/lean/bad_class.lean.expected.out).
The later contains the expected output for the test file `bad_class.lean`.
When the Lean source code or the standard library are modified, some of these
tests break because the produced output is slightly different, and we have
to reflect the changes in the `.lean.expected.out` files.
We should not blindly copy the new produced output since we may accidentally
miss a bug introduced by recent changes.
The test suite contains commands that allow us to see what changed in a convenient way.
First, we must install [meld](http://meldmerge.org/). On Ubuntu, we can do it by simply executing
```
sudo apt-get install meld
```
Now, suppose `bad_class.lean` test is broken. We can see the problem by going to `test/lean` directory and
executing
```
./test_single.sh -i bad_class.lean
```
When the `-i` option is provided, `meld` is automatically invoked
whenever there is discrepancy between the produced and expected
outputs. `meld` can also be used to repair the problems.
In Emacs, we can also execute `M-x lean4-diff-test-file` to check/diff the file of the current buffer.
To mass-copy all `.produced.out` files to the respective `.expected.out` file, use `tests/lean/copy-produced`.
When using the Nix setup, add `--keep-failed` to the `nix build` call and then call
```sh
tests/lean/copy-produced <build-dir>/source/tests/lean
```
instead where `<build-dir>` is the path printed out by `nix build`.

View File

@@ -1,48 +1,30 @@
# Development Workflow
- [Commit Convention](./commit_convention.md)
- [Building Lean](../make/index.md)
- [Ubuntu Setup](../make/ubuntu.md)
- [macOS Setup](../make/osx-10.9.md)
- [Windows MSYS2 Setup](../make/msys2.md)
- [Windows with WSL](../make/wsl.md)
- [Nix Setup (*Experimental*)](../make/nix.md)
- [Unit Testing](./testing.md)
- [Building This Manual](./mdbook.md)
- [Fixing Tests](./fixing_tests.md)
- [Debugging](./debugging.md)
- [C++ Coding Style](./dev/cpp_coding_style.md)
You will notice there is a `stage0` folder. This is for bootstrapping
the compiler development. Generally you do not change any code in
`stage0` manually. It is important that you read [bootstrapping
pipeline](bootstrap.md) so you understand how this works.
If you want to make changes to Lean itself, start by [building Lean](../make/index.html) from a clean checkout to make sure that everything is set up correctly.
After that, read on below to find out how to set up your editor for changing the Lean source code, followed by further sections of the development manual where applicable such as on the [test suite](testing.md) and [commit convention](commit_convention.md).
The dev team uses `elan` to manage which `lean` toolchain to use
locally and `elan` can be used to setup the version of Lean you are
manually building. This means you generally do not use `make
install`. You use `elan` instead.
If you are planning to make any changes that may affect the compilation of Lean itself, e.g. changes to the parser, elaborator, or compiler, you should first read about the [bootstrapping pipeline](bootstrap.md).
You should not edit the `stage0` directory except using the commands described in that section when necessary.
## Development Setup
You can use any of the [supported editors](../setup.md) for editing
the Lean source code. If you set up `elan` as below, opening `src/` as
a *workspace folder* should ensure that stage 0 will be used for file
in that directory.
You can use any of the [supported editors](../setup.md) for editing the Lean source code.
If you set up `elan` as below, opening `src/` as a *workspace folder* should ensure that stage 0 (i.e. the stage that first compiles `src/`) will be used for files in that directory.
## Dev setup using elan
### Dev setup using elan
You can use [`elan`](https://github.com/leanprover/elan) to easily
switch between stages and build configurations based on the current
directory, both for the `lean`, `leanc`, and `leanmake` binaries in your shell's
PATH and inside your editor.
To install elan, you can do so, without installing a default version of Lean, using
To install elan, you can do so, without installing a default version of Lean, using (Unix)
```bash
[Unix]
curl https://raw.githubusercontent.com/leanprover/elan/master/elan-init.sh -sSf | sh -s -- --default-toolchain none
[Windows]
```
or (Windows)
```
curl -O --location https://raw.githubusercontent.com/leanprover/elan/master/elan-init.ps1
powershell -f elan-init.ps1 --default-toolchain none
del elan-init.ps1
@@ -63,6 +45,7 @@ cd src
# make `lean` etc. point to stage0 anywhere inside `src`
elan override set lean4-stage0
```
You can also use the `+toolchain` shorthand (e.g. `lean +lean4-debug`) to switch
toolchains on the spot. `lean4-mode` will automatically use the `lean` executable
associated with the directory of the current file as long as `lean4-rootdir` is

View File

@@ -1,3 +1,12 @@
# Documentation
The Lean `doc` folder contains the [Lean Manual](https://leanprover.github.io/lean4/doc/) and is
authored in a combination of markdown (*.md) files and literate Lean files. The .lean files are
preprocessed using a tool called [LeanInk](https://github.com/leanprover/leanink) and
[Alectryon](https://github.com/Kha/alectryon) which produces a generated markdown file. We then run
`mdbook` on the result to generate the html pages.
## Settings
We are using the following settings while editing the markdown docs.
@@ -14,30 +23,84 @@ We are using the following settings while editing the markdown docs.
## Build
This manual is generated by
[mdBook](https://github.com/rust-lang/mdBook). We are currently using
a [fork](https://github.com/leanprover/mdBook) of it for the following
additional features:
### Using Nix
Building the manual using Nix (which is what the CI does) is as easy as
```bash
$ nix build --update-input lean ./doc
```
You can also open a shell with `mdbook` for running the commands mentioned below with
`nix develop ./doc#book`. Otherwise, read on.
### Manually
To build and test the book you have to preprocess the .lean files with Alectryon then use our own
fork of the Rust tool named [mdbook](https://github.com/leanprover/mdbook). We have our own fork of
mdBook with the following additional features:
* Add support for hiding lines in other languages
[#1339](https://github.com/rust-lang/mdBook/pull/1339)
* Replace calling `rustdoc --test` from `mdbook test` with `./test`
* Make `mdbook test` call the `lean` compiler to test the snippets.
* Ability to test a single chapter at a time which is handy when you
are working on that chapter. See the `--chapter` option.
To build this manual, first install the fork via
```bash
cargo install --git https://github.com/leanprover/mdBook mdbook
```
Then use e.g. [`mdbook watch`](https://rust-lang.github.io/mdBook/cli/watch.html) in the `doc/` folder:
So you need to setup these tools before you can run `mdBook`.
```bash
cd doc
mdbook watch --open # opens the output in `out/` in your default browser
```
1. install [Rust](https://www.rust-lang.org/tools/install)
which provides you with the `cargo` tool for building rust packages.
Then run the following:
```bash
cargo install --git https://github.com/leanprover/mdBook mdbook
```
Run `mdbook test` to test all `lean` code blocks.
1. Clone https://github.com/leanprover/LeanInk.git and run `lake build` then copy the resulting
executable to your `$HOME/.elan/bin` folder or `%USERPROFILE%\.elan\bin` so Alectryon can find it
there.
Using the [Nix setup](make/nix.md), you can instead open a shell with
the mdBook fork downloaded from our binary cache:
```bash
nix develop .#doc
```
1. Create a Python 3.10 environment.
1. Install the following packages:
```
python3 -m pip install git+https://github.com/Kha/alectryon.git@typeid
```
1. Now you are ready to process the *.lean files using Alectryon as follows:
```
cd lean4/doc
alectryon --frontend lean4+markup examples\palindromes.lean --backend webpage -o palindromes.lean.md
```
And repeat this for the other .lean files you care about or write a script to process them all.
1. Now you can build the book using:
```
cd lean4/doc
mdbook build
```
This will put the HTML in a `out` folder so you can load `out/index.html` in your web browser and
it should look like https://leanprover.github.io/lean4/doc/.
1. It is also handy to use e.g. [`mdbook watch`](https://rust-lang.github.io/mdBook/cli/watch.html)
in the `doc/` folder so that it keeps the html up to date while you are editing.
```bash
mdbook watch --open # opens the output in `out/` in your default browser
```
## Testing Lean Snippets
You can run the following in the `doc/` folder to test all the lean code snippets.
```bash
mdbook test
```
and you can use the `--chapter` option to test a specific chapter that you are working on:
```bash
mdbook test --chapter Array
```
Use chapter name `?` to get a list of all the chapter names.

View File

@@ -1,8 +1,6 @@
# Unit Testing
# Test Suite
You can run the unit tests after completing a build using the following:
After [building lean](../make/index.md) you can run all the tests using
After [building Lean](../make/index.md) you can run all the tests using
```
cd build/release
make test ARGS=-j4
@@ -29,10 +27,11 @@ ctest -j 4 --output-on-failure --timeout 300
To get verbose output from ctest pass the `--verbose` command line
option. Test output is normally suppressed and only summary
information is displayed. This option will show all test output
information is displayed. This option will show all test output.
Here is the summary of the test source code organization.
All these tests are included by [/src/shell/CMakeLists.txt](https://github.com/leanprover/lean4/blob/master/src/shell/CMakeLists.txt):
## Test Suite Organization
All these tests are included by [src/shell/CMakeLists.txt](https://github.com/leanprover/lean4/blob/master/src/shell/CMakeLists.txt):
- `tests/lean`: contains tests that come equipped with a
.lean.expected.out file. The driver script `test_single.sh` runs
@@ -88,11 +87,35 @@ All these tests are included by [/src/shell/CMakeLists.txt](https://github.com/l
- `tests/plugin`: tests that compiled Lean code can be loaded into
`lean` via the `--plugin` command line option.
- `tests/leanpkg`: tests the `leanpkg` program, where each sub-folder
is a complete "lean package", including:
- `cyclic`
- `user_ext`
- `user_attr`
- `user_opt`
- `prv`
- `user_attr_app`
## Fixing Tests
When the Lean source code or the standard library are modified, some of the
tests break because the produced output is slightly different, and we have
to reflect the changes in the `.lean.expected.out` files.
We should not blindly copy the new produced output since we may accidentally
miss a bug introduced by recent changes.
The test suite contains commands that allow us to see what changed in a convenient way.
First, we must install [meld](http://meldmerge.org/). On Ubuntu, we can do it by simply executing
```
sudo apt-get install meld
```
Now, suppose `bad_class.lean` test is broken. We can see the problem by going to `test/lean` directory and
executing
```
./test_single.sh -i bad_class.lean
```
When the `-i` option is provided, `meld` is automatically invoked
whenever there is discrepancy between the produced and expected
outputs. `meld` can also be used to repair the problems.
In Emacs, we can also execute `M-x lean4-diff-test-file` to check/diff the file of the current buffer.
To mass-copy all `.produced.out` files to the respective `.expected.out` file, use `tests/lean/copy-produced`.
When using the Nix setup, add `--keep-failed` to the `nix build` call and then call
```sh
tests/lean/copy-produced <build-dir>/source/tests/lean
```
instead where `<build-dir>` is the path printed out by `nix build`.

View File

@@ -348,6 +348,46 @@ TODO: describe `forIn`
TODO
## Returning early from a failed match
Inside a `do` block, the pattern `let _ ← <success> | <fail>` will continue with the rest of the block if the match on the left hand side succeeds, but will execute the right hand side and exit the block on failure:
```lean
def showUserInfo (getUsername getFavoriteColor : IO (Option String)) : IO Unit := do
let some n getUsername | IO.println "no username!"
IO.println s!"username: {n}"
let some c getFavoriteColor | IO.println "user didn't provide a favorite color!"
IO.println s!"favorite color: {c}"
-- username: JohnDoe
-- favorite color: red
#eval showUserInfo (pure <| some "JohnDoe") (pure <| some "red")
-- no username
#eval showUserInfo (pure none) (pure <| some "purple")
-- username: JaneDoe
-- user didn't provide a favorite color
#eval showUserInfo (pure <| some "JaneDoe") (pure none)
```
## If-let
Inside a `do` block, users can employ the `if let` pattern to destructure actions:
```lean
def tryIncrement (getInput : IO (Option Nat)) : IO (Except String Nat) := do
if let some n getInput
then return Except.ok n.succ
else return Except.error "argument was `none`"
-- Except.ok 2
#eval tryIncrement (pure <| some 1)
-- Except.error "argument was `none`"
#eval tryIncrement (pure <| none)
```
## Pattern matching
TODO

8
doc/elaborators.md Normal file
View File

@@ -0,0 +1,8 @@
## Elaborators
TODO. See [Lean Together 2021: Metaprogramming in Lean
4](https://youtu.be/hxQ1vvhYN_U) for an overview as well [the
continuation](https://youtu.be/vy4JWIiiXSY) about tactic programming.
For more information on antiquotations, see also §4.1 of [Beyond
Notations: Hygienic Macro Expansion for Theorem Proving
Languages](https://arxiv.org/pdf/2001.10490.pdf#page=11).

9
doc/examples.md Normal file
View File

@@ -0,0 +1,9 @@
Examples
========
- [Palindromes](examples/palindromes.lean.md)
- [Binary Search Trees](examples/bintree.lean.md)
- [A Certified Type Checker](examples/tc.lean.md)
- [The Well-Typed Interpreter](examples/interp.lean.md)
- [Dependent de Bruijn Indices](examples/deBruijn.lean.md)
- [Parametric Higher-Order Abstract Syntax](examples/phoas.lean.md)

View File

@@ -0,0 +1,46 @@
import Lean
open Lean Meta
def ctor (mvarId : MVarId) (idx : Nat) : MetaM (List MVarId) := do
/- Set `MetaM` context using `mvarId` -/
withMVarContext mvarId do
/- Fail if the metavariable is already assigned. -/
checkNotAssigned mvarId `ctor
/- Retrieve the target type, instantiateMVars, and use `whnf`. -/
let target getMVarType' mvarId
let .const declName us := target.getAppFn
| throwTacticEx `ctor mvarId "target is not an inductive datatype"
let .inductInfo { ctors, .. } getConstInfo declName
| throwTacticEx `ctor mvarId "target is not an inductive datatype"
if idx = 0 then
throwTacticEx `ctor mvarId "invalid index, it must be > 0"
else if h : idx - 1 < ctors.length then
apply mvarId (.const ctors[idx - 1] us)
else
throwTacticEx `ctor mvarId "invalid index, inductive datatype has only {ctors.length} contructors"
open Elab Tactic
elab "ctor" idx:num : tactic =>
liftMetaTactic (ctor · idx.getNat)
example (p : Prop) : p := by
ctor 1 -- Error
example (h : q) : p q := by
ctor 0 -- Error
exact h
example (h : q) : p q := by
ctor 3 -- Error
exact h
example (h : q) : p q := by
ctor 2
exact h
example (h : q) : p q := by
ctor 1
exact h -- Error

View File

@@ -0,0 +1,80 @@
import Lean
open Lean Meta
def ex1 (declName : Name) : MetaM Unit := do
let info getConstInfo declName
IO.println s!"{declName} : {← ppExpr info.type}"
if let some val := info.value? then
IO.println s!"{declName} : {← ppExpr val}"
#eval ex1 ``Nat
def ex2 (declName : Name) : MetaM Unit := do
let info getConstInfo declName
trace[Meta.debug] "{declName} : {info.type}"
if let some val := info.value? then
trace[Meta.debug] "{declName} : {val}"
#eval ex2 ``Add.add
set_option trace.Meta.debug true in
#eval ex2 ``Add.add
def ex3 (declName : Name) : MetaM Unit := do
let info getConstInfo declName
forallTelescope info.type fun xs type => do
trace[Meta.debug] "hypotheses : {xs}"
trace[Meta.debug] "resultType : {type}"
for x in xs do
trace[Meta.debug] "{x} : {← inferType x}"
def myMin [LT α] [DecidableRel (α := α) (·<·)] (a b : α) : α :=
if a < b then
a
else
b
set_option trace.Meta.debug true in
#eval ex3 ``myMin
def ex4 : MetaM Unit := do
let nat := mkConst ``Nat
withLocalDeclD `a nat fun a =>
withLocalDeclD `b nat fun b => do
let e mkAppM ``HAdd.hAdd #[a, b]
trace[Meta.debug] "{e} : {← inferType e}"
let e mkAdd a (mkNatLit 5)
trace[Meta.debug] "added 5: {e}"
let e whnf e
trace[Meta.debug] "whnf: {e}"
let e reduce e
trace[Meta.debug] "reduced: {e}"
let a_plus_1 mkAdd a (mkNatLit 1)
let succ_a := mkApp (mkConst ``Nat.succ) a
trace[Meta.debug] "({a_plus_1} =?= {succ_a}) == {← isDefEq a_plus_1 succ_a}"
let m mkFreshExprMVar nat
let m_plus_1 mkAdd m (mkNatLit 1)
trace[Meta.debug] "m_plus_1: {m_plus_1}"
unless ( isDefEq m_plus_1 succ_a) do throwError "isDefEq failed"
trace[Meta.debug] "m_plus_1: {m_plus_1}"
set_option trace.Meta.debug true in
#eval ex4
open Elab Term
def ex5 : TermElabM Unit := do
let nat := Lean.mkConst ``Nat
withLocalDeclD `a nat fun a => do
withLocalDeclD `b nat fun b => do
let ab mkAppM ``HAdd.hAdd #[a, b]
let stx `(fun x => if x < 10 then $( exprToSyntax ab) + x else x + $( exprToSyntax a))
let e elabTerm stx none
trace[Meta.debug] "{e} : {← inferType e}"
let e := mkApp e (mkNatLit 5)
let e whnf e
trace[Meta.debug] "{e}"
set_option trace.Meta.debug true in
#eval ex5

View File

@@ -0,0 +1,49 @@
import Lean
def f (x y : Nat) := x * y + 1
infixl:65 " *' " => f
#check 2 *' 3
notation "unitTest " x => Prod.mk x ()
#check unitTest 42
notation "parenthesisTest " x => Nat.sub (x)
#check parenthesisTest 12
def Set (α : Type u) := α Prop
def setOf {α : Type} (p : α Prop) : Set α := p
notation "{ " x " | " p " }" => setOf (fun x => p)
#check { x | x 1 }
notation "cdotTest " "(" x ", " y ")" => Prod.map (· + 1) (1 + ·) (x, y)
#check cdotTest (13, 12)
notation "tupleFunctionTest " "(" x ", " y ")"=> Prod.map (Nat.add 1) (Nat.add 2) (x, y)
#check tupleFunctionTest (15, 12)
notation "diag " x => Prod.mk x x
#check diag 12
open Lean Meta PrettyPrinter Delaborator SubExpr in
@[delab app.Prod.mk] def delabDoubleRhsTest : Delab := do
let e getExpr
let #[_, _, x, y] := e.getAppArgs | failure
guard ( isDefEq x y)
let stx withAppArg delab
`(diag $stx)
#check diag 3
#check (3, 3)
#check (3, 4)
#check (2+1, 3)
#check (true, true)

View File

@@ -0,0 +1,22 @@
/- "Hello world" -/
#eval "hello" ++ " " ++ "world"
-- "hello world"
#check true
-- Bool
def x := 10
#eval x + 2
-- 12
def double (x : Int) := 2*x
#eval double 3
-- 6
#check double
-- Int → Int
example : double 4 = 8 := rfl

View File

@@ -0,0 +1,19 @@
/- Dependent pattern matching -/
inductive Vector (α : Type u) : Nat Type u
| nil : Vector α 0
| cons : α Vector α n Vector α (n+1)
infix:67 "::" => Vector.cons
def Vector.zip : Vector α n Vector β n Vector (α × β) n
| nil, nil => nil
| a::as, b::bs => (a, b) :: zip as bs
#print Vector.zip
/-
def Vector.zip.{u_1, u_2} : {α : Type u_1} → {n : Nat} → {β : Type u_2} → Vector α n → Vector β n → Vector (α × β) n :=
fun {α} {n} {β} x x_1 =>
Vector.brecOn (motive := fun {n} x => {β : Type u_2} → Vector β n → Vector (α × β) n) x
...
-/

View File

@@ -0,0 +1,22 @@
/- Structures -/
structure Point where
x : Int := 0
y : Int := 0
deriving Repr
#eval Point.x (Point.mk 10 20)
-- 10
#eval { x := 10, y := 20 : Point }
def p : Point := { y := 20 }
#eval p.x
#eval p.y
#eval { p with x := 5 }
-- { x := 5, y := 20 }
structure Point3D extends Point where
z : Int

View File

@@ -0,0 +1,28 @@
/- Type classes -/
namespace Example
class ToString (α : Type u) where
toString : α String
#check @ToString.toString
-- {α : Type u_1} → [self : ToString α] → α → String
instance : ToString String where
toString s := s
instance : ToString Bool where
toString b := if b then "true" else "false"
#eval ToString.toString "hello"
export ToString (toString)
#eval toString true
-- "true"
-- #eval toString (true, "hello") -- Error
instance [ToString α] [ToString β] : ToString (α × β) where
toString p := "(" ++ toString p.1 ++ ", " ++ toString p.2 ++ ")"
#eval toString (true, "hello")
-- "(true, hello)"
end Example

View File

@@ -0,0 +1,44 @@
/- Type classes are heavily used in Lean -/
namespace Example
class Mul (α : Type u) where
mul : α α α
infixl:70 " * " => Mul.mul
def double [Mul α] (a : α) := a * a
class Semigroup (α : Type u) extends Mul α where
mul_assoc : a b c : α, (a * b) * c = a * (b * c)
instance : Semigroup Nat where
mul := Nat.mul
mul_assoc := Nat.mul_assoc
#eval double 5
class Functor (f : Type u Type v) : Type (max (u+1) v) where
map : (α β) f α f β
infixr:100 " <$> " => Functor.map
class LawfulFunctor (f : Type u Type v) [Functor f] : Prop where
id_map (x : f α) : id <$> x = x
comp_map (g : α β) (h : β γ) (x : f α) :(h g) <$> x = h <$> g <$> x
end Example
/-
`Deriving instances automatically`
We have seen `deriving Repr` in a few examples.
It is an instance generator.
Lean comes equipped with generators for the following classes.
`Repr`, `Inhabited`, `BEq`, `DecidableEq`,
`Hashable`, `Ord`, `FromToJson`, `SizeOf`
-/
inductive Tree (α : Type u) where
| leaf (val : α)
| node (left right : Tree α)
deriving DecidableEq, Ord, Inhabited, Repr

View File

@@ -0,0 +1,31 @@
/- Tactics -/
example : p q p q p := by
intro hp hq
apply And.intro
exact hp
apply And.intro
exact hq
exact hp
example : p q p q p := by
intro hp hq; apply And.intro hp; exact And.intro hq hp
/- Structuring proofs -/
example : p q p q p := by
intro hp hq
apply And.intro
case left => exact hp
case right =>
apply And.intro
case left => exact hq
case right => exact hp
example : p q p q p := by
intro hp hq
apply And.intro
. exact hp
. apply And.intro
. exact hq
. exact hp

View File

@@ -0,0 +1,19 @@
/- intro tactic variants -/
example (p q : α Prop) : ( x, p x q x) x, q x p x := by
intro h
match h with
| Exists.intro w (And.intro hp hq) => exact Exists.intro w (And.intro hq hp)
example (p q : α Prop) : ( x, p x q x) x, q x p x := by
intro (Exists.intro _ (And.intro hp hq))
exact Exists.intro _ (And.intro hq hp)
example (p q : α Prop) : ( x, p x q x) x, q x p x := by
intro _, hp, hq
exact _, hq, hp
example (α : Type) (p q : α Prop) : ( x, p x q x) x, q x p x := by
intro
| _, .inl h => exact _, .inr h
| _, .inr h => exact _, .inl h

View File

@@ -0,0 +1,12 @@
/- Inaccessible names -/
example : x y : Nat, x = y y = x := by
intros
apply Eq.symm
assumption
example : x y : Nat, x = y y = x := by
intros
apply Eq.symm
rename_i a b hab
exact hab

View File

@@ -0,0 +1,19 @@
/- More tactics -/
example (p q : Nat Prop) : ( x, p x q x) x, q x p x := by
intro h
cases h with
| intro x hpq =>
cases hpq with
| intro hp hq =>
exists x
example : p q q p := by
intro p
cases p
constructor <;> assumption
example : p ¬ p q := by
intro h
cases h
contradiction

View File

@@ -0,0 +1,20 @@
/- Structuring proofs (cont.) -/
example : p (q r) (p q) (p r) := by
intro h
have hp : p := h.left
have hqr : q r := h.right
show (p q) (p r)
cases hqr with
| inl hq => exact Or.inl hp, hq
| inr hr => exact Or.inr hp, hr
example : p (q r) (p q) (p r) := by
intro hp, hqr
cases hqr with
| inl hq =>
have := And.intro hp hq
apply Or.inl; exact this
| inr hr =>
have := And.intro hp hr
apply Or.inr; exact this

View File

@@ -0,0 +1,10 @@
/- Tactic combinators -/
example : p q r p ((p q) r) (q r p) := by
intros
repeat (any_goals constructor)
all_goals assumption
example : p q r p ((p q) r) (q r p) := by
intros
repeat (any_goals (first | assumption | constructor))

View File

@@ -0,0 +1,14 @@
/- First-class functions -/
def twice (f : Nat Nat) (a : Nat) :=
f (f a)
#check twice
-- (Nat → Nat) → Nat → Nat
#eval twice (fun x => x + 2) 10
theorem twice_add_2 (a : Nat) : twice (fun x => x + 2) a = a + 4 := rfl
-- `(· + 2)` is syntax sugar for `(fun x => x + 2)`.
#eval twice (· + 2) 10

View File

@@ -0,0 +1,22 @@
/- Rewriting -/
example (f : Nat Nat) (k : Nat) (h₁ : f 0 = 0) (h₂ : k = 0) : f k = 0 := by
rw [h₂] -- replace k with 0
rw [h₁] -- replace f 0 with 0
example (f : Nat Nat) (k : Nat) (h₁ : f 0 = 0) (h₂ : k = 0) : f k = 0 := by
rw [h₂, h₁]
example (f : Nat Nat) (a b : Nat) (h₁ : a = b) (h₂ : f a = 0) : f b = 0 := by
rw [ h₁, h₂]
example (f : Nat Nat) (a : Nat) (h : 0 + a = 0) : f a = f 0 := by
rw [Nat.zero_add] at h
rw [h]
def Tuple (α : Type) (n : Nat) :=
{ as : List α // as.length = n }
example (n : Nat) (h : n = 0) (t : Tuple α n) : Tuple α 0 := by
rw [h] at t
exact t

View File

@@ -0,0 +1,21 @@
/- Simplifier -/
example (p : Nat Prop) : (x + 0) * (0 + y * 1 + z * 0) = x * y := by
simp
example (p : Nat Prop) (h : p (x * y)) : p ((x + 0) * (0 + y * 1 + z * 0)) := by
simp; assumption
example (p : Nat Prop) (h : p ((x + 0) * (0 + y * 1 + z * 0))) : p (x * y) := by
simp at h; assumption
def f (m n : Nat) : Nat :=
m + n + m
example (h : n = 1) (h' : 0 = m) : (f m n) = n := by
simp [h, h', f]
example (p : Nat Prop) (h₁ : x + 0 = x') (h₂ : y + 0 = y')
: x + y + 0 = x' + y' := by
simp at *
simp [*]

View File

@@ -0,0 +1,13 @@
/- Simplifier -/
def mk_symm (xs : List α) :=
xs ++ xs.reverse
@[simp] theorem reverse_mk_symm : (mk_symm xs).reverse = mk_symm xs := by
simp [mk_symm]
theorem tst : (xs ++ mk_symm ys).reverse = mk_symm ys ++ xs.reverse := by
simp
#print tst
-- Lean reverse_mk_symm, and List.reverse_append

View File

@@ -0,0 +1,26 @@
/- split tactic -/
def f (x y z : Nat) : Nat :=
match x, y, z with
| 5, _, _ => y
| _, 5, _ => y
| _, _, 5 => y
| _, _, _ => 1
example : x 5 y 5 z 5 z = w f x y w = 1 := by
intros
simp [f]
split
. contradiction
. contradiction
. contradiction
. rfl
def g (xs ys : List Nat) : Nat :=
match xs, ys with
| [a, b], _ => a+b+1
| _, [b, c] => b+1
| _, _ => 1
example (xs ys : List Nat) (h : g xs ys = 0) : False := by
unfold g at h; split at h <;> simp_arith at h

View File

@@ -0,0 +1,9 @@
/- induction tactic -/
example (as : List α) (a : α) : (as.concat a).length = as.length + 1 := by
induction as with
| nil => rfl
| cons x xs ih => simp [List.concat, ih]
example (as : List α) (a : α) : (as.concat a).length = as.length + 1 := by
induction as <;> simp! [*]

View File

@@ -0,0 +1,59 @@
/- Enumerated types -/
inductive Weekday where
| sunday | monday | tuesday | wednesday
| thursday | friday | saturday
#check Weekday.sunday
-- Weekday
open Weekday
#check sunday
def natOfWeekday (d : Weekday) : Nat :=
match d with
| sunday => 1
| monday => 2
| tuesday => 3
| wednesday => 4
| thursday => 5
| friday => 6
| saturday => 7
def Weekday.next (d : Weekday) : Weekday :=
match d with
| sunday => monday
| monday => tuesday
| tuesday => wednesday
| wednesday => thursday
| thursday => friday
| friday => saturday
| saturday => sunday
def Weekday.previous : Weekday Weekday
| sunday => saturday
| monday => sunday
| tuesday => monday
| wednesday => tuesday
| thursday => wednesday
| friday => thursday
| saturday => friday
/- Proving theorems using tactics -/
theorem Weekday.next_previous (d : Weekday) : d.next.previous = d :=
match d with
| sunday => rfl
| monday => rfl
| tuesday => rfl
| wednesday => rfl
| thursday => rfl
| friday => rfl
| saturday => rfl
theorem Weekday.next_previous' (d : Weekday) : d.next.previous = d := by -- switch to tactic mode
cases d -- Creates 7 goals
rfl; rfl; rfl; rfl; rfl; rfl; rfl
theorem Weekday.next_previous'' (d : Weekday) : d.next.previous = d := by
cases d <;> rfl

View File

@@ -0,0 +1,20 @@
/- What is the type of Nat? -/
#check 0
-- Nat
#check Nat
-- Type
#check Type
-- Type 1
#check Type 1
-- Type 2
#check Eq.refl 2
-- 2 = 2
#check 2 = 2
-- Prop
#check Prop
-- Type
example : Prop = Sort 0 := rfl
example : Type = Sort 1 := rfl
example : Type 1 = Sort 2 := rfl

View File

@@ -0,0 +1,21 @@
/- Implicit arguments and universe polymorphism -/
def f (α β : Sort u) (a : α) (b : β) : α := a
#eval f Nat String 1 "hello"
-- 1
def g {α β : Sort u} (a : α) (b : β) : α := a
#eval g 1 "hello"
def h (a : α) (b : β) : α := a
#check g
-- ?m.1 → ?m.2 → ?m.1
#check @g
-- {α β : Sort u} → α → β → α
#check @h
-- {α : Sort u_1} → {β : Sort u_2} → α → β → α
#check g (α := Nat) (β := String)
-- Nat → String → Nat

View File

@@ -0,0 +1,14 @@
/- Inductive Types -/
inductive Tree (β : Type v) where
| leaf
| node (left : Tree β) (key : Nat) (value : β) (right : Tree β)
deriving Repr
#eval Tree.node .leaf 10 true .leaf
-- Tree.node Tree.leaf 10 true Tree.leaf
inductive Vector (α : Type u) : Nat Type u
| nil : Vector α 0
| cons : α Vector α n Vector α (n+1)

View File

@@ -0,0 +1,25 @@
/- Recursive functions -/
#print Nat -- Nat is an inductive datatype
def fib (n : Nat) : Nat :=
match n with
| 0 => 1
| 1 => 1
| n+2 => fib (n+1) + fib n
example : fib 5 = 8 := rfl
example : fib (n+2) = fib (n+1) + fib n := rfl
#print fib
/-
def fib : Nat → Nat :=
fun n =>
Nat.brecOn n fun n f =>
(match (motive := (n : Nat) → Nat.below n → Nat) n with
| 0 => fun x => 1
| 1 => fun x => 1
| Nat.succ (Nat.succ n) => fun x => x.fst.fst + x.fst.snd.fst.fst)
f
-/

View File

@@ -0,0 +1,25 @@
/- Well-founded recursion -/
def ack : Nat Nat Nat
| 0, y => y+1
| x+1, 0 => ack x 1
| x+1, y+1 => ack x (ack (x+1) y)
termination_by ack x y => (x, y)
def sum (a : Array Int) : Int :=
let rec go (i : Nat) :=
if i < a.size then
a[i] + go (i+1)
else
0
go 0
termination_by go i => a.size - i
set_option pp.proofs true
#print sum.go
/-
def sum.go : Array Int → Nat → Int :=
fun a =>
WellFounded.fix (sum.go.proof_1 a) fun i a_1 =>
if h : i < Array.size a then Array.getOp a i + a_1 (i + 1) (sum.go.proof_2 a i h) else 0
-/

View File

@@ -0,0 +1,44 @@
/- Mutual recursion -/
inductive Term where
| const : String Term
| app : String List Term Term
namespace Term
mutual
def numConsts : Term Nat
| const _ => 1
| app _ cs => numConstsLst cs
def numConstsLst : List Term Nat
| [] => 0
| c :: cs => numConsts c + numConstsLst cs
end
mutual
def replaceConst (a b : String) : Term Term
| const c => if a = c then const b else const c
| app f cs => app f (replaceConstLst a b cs)
def replaceConstLst (a b : String) : List Term List Term
| [] => []
| c :: cs => replaceConst a b c :: replaceConstLst a b cs
end
/- Mutual recursion in theorems -/
mutual
theorem numConsts_replaceConst (a b : String) (e : Term)
: numConsts (replaceConst a b e) = numConsts e := by
match e with
| const c => simp [replaceConst]; split <;> simp [numConsts]
| app f cs => simp [replaceConst, numConsts, numConsts_replaceConstLst a b cs]
theorem numConsts_replaceConstLst (a b : String) (es : List Term)
: numConstsLst (replaceConstLst a b es) = numConstsLst es := by
match es with
| [] => simp [replaceConstLst, numConstsLst]
| c :: cs =>
simp [replaceConstLst, numConstsLst, numConsts_replaceConst a b c,
numConsts_replaceConstLst a b cs]
end

295
doc/examples/bintree.lean Normal file
View File

@@ -0,0 +1,295 @@
/-!
# Binary Search Trees
If the type of keys can be totally ordered -- that is, it supports a well-behaved `≤` comparison --
then maps can be implemented with binary search trees (BSTs). Insert and lookup operations on BSTs take time
proportional to the height of the tree. If the tree is balanced, the operations therefore take logarithmic time.
This example is based on a similar example found in the ["Sofware Foundations"](https://softwarefoundations.cis.upenn.edu/vfa-current/SearchTree.html)
book (volume 3).
-/
/-!
We use `Nat` as the key type in our implementation of BSTs,
since it has a convenient total order with lots of theorems and automation available.
We leave as an exercise to the reader the generalization to arbitrary types.
-/
inductive Tree (β : Type v) where
| leaf
| node (left : Tree β) (key : Nat) (value : β) (right : Tree β)
deriving Repr
/-!
The function `contains` returns `true` iff the given tree contains the key `k`.
-/
def Tree.contains (t : Tree β) (k : Nat) : Bool :=
match t with
| leaf => false
| node left key value right =>
if k < key then
left.contains k
else if key < k then
right.contains k
else
true
/-!
`t.find? k` returns `some v` if `v` is the value bound to key `k` in the tree `t`. It returns `none` otherwise.
-/
def Tree.find? (t : Tree β) (k : Nat) : Option β :=
match t with
| leaf => none
| node left key value right =>
if k < key then
left.find? k
else if key < k then
right.find? k
else
some value
/-!
`t.insert k v` is the map containing all the bindings of `t` along with a binding of `k` to `v`.
-/
def Tree.insert (t : Tree β) (k : Nat) (v : β) : Tree β :=
match t with
| leaf => node leaf k v leaf
| node left key value right =>
if k < key then
node (left.insert k v) key value right
else if key < k then
node left key value (right.insert k v)
else
node left k v right
/-!
Let's add a new operation to our tree: converting it to an association list that contains the key--value bindings from the tree stored as pairs.
If that list is sorted by the keys, then any two trees that represent the same map would be converted to the same list.
Here's a function that does so with an in-order traversal of the tree.
-/
def Tree.toList (t : Tree β) : List (Nat × β) :=
match t with
| leaf => []
| node l k v r => l.toList ++ [(k, v)] ++ r.toList
#eval Tree.leaf.insert 2 "two"
|>.insert 3 "three"
|>.insert 1 "one"
#eval Tree.leaf.insert 2 "two"
|>.insert 3 "three"
|>.insert 1 "one"
|>.toList
/-!
The implemention of `Tree.toList` is inefficient because of how it uses the `++` operator.
On a balanced tree its running time is linearithmic, because it does a linear number of
concatentations at each level of the tree. On an unbalanced tree it's quadratic time.
Here's a tail-recursive implementation than runs in linear time, regardless of whether the tree is balanced:
-/
def Tree.toListTR (t : Tree β) : List (Nat × β) :=
go t []
where
go (t : Tree β) (acc : List (Nat × β)) : List (Nat × β) :=
match t with
| leaf => acc
| node l k v r => go l ((k, v) :: go r acc)
/-!
We now prove that `t.toList` and `t.toListTR` return the same list.
The proof is on induction, and as we used the auxiliary function `go`
to define `Tree.toListTR`, we use the auxiliary theorem `go` to prove the theorem.
The proof of the auxiliary theorem is by induction on `t`.
The `generalizing acc` modifier instructs Lean to revert `acc`, apply the
induction theorem for `Tree`s, and then reintroduce `acc` in each case.
By using `generalizing`, we obtain the more general induction hypotheses
- `left_ih : ∀ acc, toListTR.go left acc = toList left ++ acc`
- `right_ih : ∀ acc, toListTR.go right acc = toList right ++ acc`
Recall that the combinator `tac <;> tac'` runs `tac` on the main goal and `tac'` on each produced goal,
concatenating all goals produced by `tac'`. In this theorem, we use it to apply
`simp` and close each subgoal produced by the `induction` tactic.
The `simp` parameters `toListTR.go` and `toList` instruct the simplifier to try to reduce
and/or apply auto generated equation theorems for these two functions.
The parameter `*` intructs the simplifier to use any equation in a goal as rewriting rules.
In this particular case, `simp` uses the induction hypotheses as rewriting rules.
Finally, the parameter `List.append_assoc` intructs the simplifier to use the
`List.append_assoc` theorem as a rewriting rule.
-/
theorem Tree.toList_eq_toListTR (t : Tree β)
: t.toList = t.toListTR := by
simp [toListTR, go t []]
where
go (t : Tree β) (acc : List (Nat × β))
: toListTR.go t acc = t.toList ++ acc := by
induction t generalizing acc <;>
simp [toListTR.go, toList, *, List.append_assoc]
/-!
The `[csimp]` annotation instructs the Lean code generator to replace
any `Tree.toList` with `Tree.toListTR` when generating code.
-/
@[csimp] theorem Tree.toList_eq_toListTR_csimp
: @Tree.toList = @Tree.toListTR := by
funext β t
apply toList_eq_toListTR
/-!
The implementations of `Tree.find?` and `Tree.insert` assume that values of type tree obey the BST invariant:
for any non-empty node with key `k`, all the values of the `left` subtree are less than `k` and all the values
of the right subtree are greater than `k`. But that invariant is not part of the definition of tree.
So, let's formalize the BST invariant. Here's one way to do so. First, we define a helper `ForallTree`
to express that idea that a predicate holds at every node of a tree:
-/
inductive ForallTree (p : Nat β Prop) : Tree β Prop
| leaf : ForallTree p .leaf
| node :
ForallTree p left
p key value
ForallTree p right
ForallTree p (.node left key value right)
/-!
Second, we define the BST invariant:
An empty tree is a BST.
A non-empty tree is a BST if all its left nodes have a lesser key, its right nodes have a greater key, and the left and right subtrees are themselves BSTs.
-/
inductive BST : Tree β Prop
| leaf : BST .leaf
| node :
ForallTree (fun k v => k < key) left
ForallTree (fun k v => key < k) right
BST left BST right
BST (.node left key value right)
/-!
We can use the `macro` command to create helper tactics for organizing our proofs.
The macro `have_eq x y` tries to prove `x = y` using linear arithmetic, and then
immediately uses the new equality to substitute `x` with `y` everywhere in the goal.
The modifier `local` specifies the scope of the macro.
-/
/-- The `have_eq lhs rhs` tactic (tries to) prove that `lhs = rhs`,
and then replaces `lhs` with `rhs`. -/
local macro "have_eq " lhs:term:max rhs:term:max : tactic =>
`((have h : $lhs = $rhs :=
-- TODO: replace with linarith
by simp_arith at *; apply Nat.le_antisymm <;> assumption
try subst $lhs))
/-!
The `by_cases' e` is just the regular `by_cases` followed by `simp` using all
hypotheses in the current goal as rewriting rules.
Recall that the `by_cases` tactic creates two goals. One where we have `h : e` and
another one containing `h : ¬ e`. The simplier uses the `h` to rewrite `e` to `True`
in the first subgoal, and `e` to `False` in the second. This is particularly
useful if `e` is the condition of an `if`-statement.
-/
/-- `by_cases' e` is a shorthand form `by_cases e <;> simp[*]` -/
local macro "by_cases' " e:term : tactic =>
`(by_cases $e <;> simp [*])
/-!
We can use the attribute `[simp]` to instruct the simplifier to reduce given definitions or
apply rewrite theorems. The `local` modifier limits the scope of this modification to this file.
-/
attribute [local simp] Tree.insert
/-!
We now prove that `Tree.insert` preserves the BST invariant using induction and case analysis.
Recall that the tactic `. tac` focuses on the main goal and tries to solve it using `tac`, or else fails.
It is used to structure proofs in Lean.
The notation `e` is just syntax sugar for `(by assumption : e)`. That is, it tries to find a hypothesis `h : e`.
It is useful to access hypothesis that have auto generated names (aka "inaccessible") names.
-/
theorem Tree.forall_insert_of_forall
(h₁ : ForallTree p t) (h₂ : p key value)
: ForallTree p (t.insert key value) := by
induction h₁ with
| leaf => exact .node .leaf h₂ .leaf
| node hl hp hr ihl ihr =>
rename Nat => k
by_cases' key < k
. exact .node ihl hp hr
. by_cases' k < key
. exact .node hl hp ihr
. have_eq key k
exact .node hl h₂ hr
theorem Tree.bst_insert_of_bst
{t : Tree β} (h : BST t) (key : Nat) (value : β)
: BST (t.insert key value) := by
induction h with
| leaf => exact .node .leaf .leaf .leaf .leaf
| node h₁ h₂ b₁ b₂ ih₁ ih₂ =>
rename Nat => k
simp
by_cases' key < k
. exact .node (forall_insert_of_forall h₁ key < k) h₂ ih₁ b₂
. by_cases' k < key
. exact .node h₁ (forall_insert_of_forall h₂ k < key) b₁ ih₂
. have_eq key k
exact .node h₁ h₂ b₁ b₂
/-!
Now, we define the type `BinTree` using a `Subtype` that states that only trees satisfying the BST invariant are `BinTree`s.
-/
def BinTree (β : Type u) := { t : Tree β // BST t }
def BinTree.mk : BinTree β :=
.leaf, .leaf
def BinTree.contains (b : BinTree β) (k : Nat) : Bool :=
b.val.contains k
def BinTree.find? (b : BinTree β) (k : Nat) : Option β :=
b.val.find? k
def BinTree.insert (b : BinTree β) (k : Nat) (v : β) : BinTree β :=
b.val.insert k v, b.val.bst_insert_of_bst b.property k v
/-!
Finally, we prove that `BinTree.find?` and `BinTree.insert` satisfy the map properties.
-/
attribute [local simp]
BinTree.mk BinTree.contains BinTree.find?
BinTree.insert Tree.find? Tree.contains Tree.insert
theorem BinTree.find_mk (k : Nat)
: BinTree.mk.find? k = (none : Option β) := by
simp
theorem BinTree.find_insert (b : BinTree β) (k : Nat) (v : β)
: (b.insert k v).find? k = some v := by
let t, h := b; simp
induction t with simp
| node left key value right ihl ihr =>
by_cases' k < key
. cases h; apply ihl; assumption
. by_cases' key < k
cases h; apply ihr; assumption
theorem BinTree.find_insert_of_ne (b : BinTree β) (h : k k') (v : β)
: (b.insert k v).find? k' = b.find? k' := by
let t, h := b; simp
induction t with simp
| leaf =>
split <;> simp <;> split <;> simp
have_eq k k'
contradiction
| node left key value right ihl ihr =>
let .node hl hr bl br := h
specialize ihl bl
specialize ihr br
by_cases' k < key; by_cases' key < k
have_eq key k
by_cases' k' < k; by_cases' k < k'
have_eq k k'
contradiction

View File

@@ -0,0 +1,5 @@
(this example is rendered by Alectryon in the CI)
```lean
{{#include bintree.lean}}
```

163
doc/examples/deBruijn.lean Normal file
View File

@@ -0,0 +1,163 @@
/-!
# Dependent de Bruijn Indices
In this example, we represent program syntax terms in a type family parameterized by a list of types,
representing the typing context, or information on which free variables are in scope and what
their types are.
Remark: this example is based on an example in the book [Certified Programming with Dependent Types](http://adam.chlipala.net/cpdt/) by Adam Chlipala.
-/
/-!
Programmers who move to statically typed functional languages from scripting languages
often complain about the requirement that every element of a list have the same type. With
fancy type systems, we can partially lift this requirement. We can index a list type with a
“type-level” list that explains what type each element of the list should have. This has been
done in a variety of ways in Haskell using type classes, and we can do it much more cleanly
and directly in Lean.
We parameterize our heterogeneous lists by at type `α` and an `α`-indexed type `β`.
-/
inductive HList {α : Type v} (β : α Type u) : List α Type (max u v)
| nil : HList β []
| cons : β i HList β is HList β (i::is)
/-!
We overload the `List.cons` notation `::` so we can also use it to create
heterogeneous lists.
-/
infix:67 " :: " => HList.cons
/-! We similarly overload the `List` notation `[]` for the empty heterogeneous list. -/
notation "[" "]" => HList.nil
/-!
Variables are represented in a way isomorphic to the natural numbers, where
number 0 represents the first element in the context, number 1 the second element, and so
on. Actually, instead of numbers, we use the `Member` inductive family.
The value of type `Member a as` can be viewed as a certificate that `a` is
an element of the list `as`. The constructor `Member.head` says that `a`
is in the list if the list begins with it. The constructor `Member.tail`
says that if `a` is in the list `bs`, it is also in the list `b::bs`.
-/
inductive Member : α List α Type
| head : Member a (a::as)
| tail : Member a bs Member a (b::bs)
/-!
Given a heterogeneous list `HList β is` and value of type `Member i is`, `HList.get`
retrieves an element of type `β i` from the list.
The pattern `.head` and `.tail h` are sugar for `Member.head` and `Member.tail h` respectively.
Lean can infer the namespace using the expected type.
-/
def HList.get : HList β is Member i is β i
| a::as, .head => a
| a::as, .tail h => as.get h
/-!
Here is the definition of the simple type system for our programming language, a simply typed
lambda calculus with natural numbers as the base type.
-/
inductive Ty where
| nat
| fn : Ty Ty Ty
/-!
We can write a function to translate `Ty` values to a Lean type
— remember that types are first class, so can be calculated just like any other value.
We mark `Ty.denote` as `[reducible]` to make sure the typeclass resolution procedure can
unfold/reduce it. For example, suppose Lean is trying to synthesize a value for the instance
`Add (Ty.denote Ty.nat)`. Since `Ty.denote` is marked as `[reducible]`,
the typeclass resolution procedure can reduce `Ty.denote Ty.nat` to `Nat`, and use
the builtin instance for `Add Nat` as the solution.
Recall that the term `a.denote` is sugar for `denote a` where `denote` is the function being defined.
We call it the "dot notation".
-/
@[reducible] def Ty.denote : Ty Type
| nat => Nat
| fn a b => a.denote b.denote
/-!
Here is the definition of the `Term` type, including variables, constants, addition,
function application and abstraction, and let binding of local variables.
Since `let` is a keyword in Lean, we use the "escaped identifier" `«let»`.
You can input the unicode (French double quotes) using `\f<<` (for `«`) and `\f>>` (for `»`).
The term `Term ctx .nat` is sugar for `Term ctx Ty.nat`, Lean infers the namespace using the expected type.
-/
inductive Term : List Ty Ty Type
| var : Member ty ctx Term ctx ty
| const : Nat Term ctx .nat
| plus : Term ctx .nat Term ctx .nat Term ctx .nat
| app : Term ctx (.fn dom ran) Term ctx dom Term ctx ran
| lam : Term (dom :: ctx) ran Term ctx (.fn dom ran)
| «let» : Term ctx ty₁ Term (ty₁ :: ctx) ty₂ Term ctx ty₂
/-!
Here are two example terms encoding, the first addition packaged as a two-argument
curried function, and the second of a sample application of addition to constants.
The command `open Ty Term Member` opens the namespaces `Ty`, `Term`, and `Member`. Thus,
you can write `lam` instead of `Term.lam`.
-/
open Ty Term Member
def add : Term [] (fn nat (fn nat nat)) :=
lam (lam (plus (var (tail head)) (var head)))
def three_the_hard_way : Term [] nat :=
app (app add (const 1)) (const 2)
/-!
Since dependent typing ensures that any term is well-formed in its context and has a particular type,
it is easy to translate syntactic terms into Lean values.
The attribute `[simp]` instructs Lean to always try to unfold `Term.denote` applications when one applies
the `simp` tactic. We also say this is a hint for the Lean term simplifier.
-/
@[simp] def Term.denote : Term ctx ty HList Ty.denote ctx ty.denote
| var h, env => env.get h
| const n, _ => n
| plus a b, env => a.denote env + b.denote env
| app f a, env => f.denote env (a.denote env)
| lam b, env => fun x => b.denote (x :: env)
| «let» a b, env => b.denote (a.denote env :: env)
/-!
You can show that the denotation of `three_the_hard_way` is indeed `3` using reflexivity.
-/
example : three_the_hard_way.denote [] = 3 :=
rfl
/-!
We now define the constant folding optimization that traverses a term if replaces subterms such as
`plus (const m) (const n)` with `const (n+m)`.
-/
@[simp] def Term.constFold : Term ctx ty Term ctx ty
| const n => const n
| var h => var h
| app f a => app f.constFold a.constFold
| lam b => lam b.constFold
| «let» a b => «let» a.constFold b.constFold
| plus a b =>
match a.constFold, b.constFold with
| const n, const m => const (n+m)
| a', b' => plus a' b'
/-!
The correctness of the `Term.constFold` is proved using induction, case-analysis, and the term simplifier.
We prove all cases but the one for `plus` using `simp [*]`. This tactic instructs the term simplifier to
use hypotheses such as `a = b` as rewriting/simplications rules.
We use the `split` to break the nested `match` expression in the `plus` case into two cases.
The local variables `iha` and `ihb` are the induction hypotheses for `a` and `b`.
The modifier `←` in a term simplifier argument instructs the term simplier to use the equation as a rewriting rule in
the "reverse direction". That is, given `h : a = b`, `← h` instructs the term simplifier to rewrite `b` subterms to `a`.
-/
theorem Term.constFold_sound (e : Term ctx ty) : e.constFold.denote env = e.denote env := by
induction e with simp [*]
| plus a b iha ihb =>
split
next he₁ he₂ => simp [ iha, ihb, he₁, he₂]
next => simp [iha, ihb]

View File

@@ -0,0 +1,5 @@
(this example is rendered by Alectryon in the CI)
```lean
{{#include deBruijn.lean}}
```

152
doc/examples/interp.lean Normal file
View File

@@ -0,0 +1,152 @@
/-!
# The Well-Typed Interpreter
In this example, we build an interpreter for a simple functional programming language,
with variables, function application, binary operators and an `if...then...else` construct.
We will use the dependent type system to ensure that any programs which can be represented are well-typed.
Remark: this example is based on an example found in the Idris manual.
-/
/-!
Vectors
--------
A `Vector` is a list of size `n` whose elements belong to a type `α`.
-/
inductive Vector (α : Type u) : Nat Type u
| nil : Vector α 0
| cons : α Vector α n Vector α (n+1)
/-!
We can overload the `List.cons` notation `::` and use it to create `Vector`s.
-/
infix:67 " :: " => Vector.cons
/-!
Now, we define the types of our simple functional language.
We have integers, booleans, and functions, represented by `Ty`.
-/
inductive Ty where
| int
| bool
| fn (a r : Ty)
/-!
We can write a function to translate `Ty` values to a Lean type
— remember that types are first class, so can be calculated just like any other value.
We mark `Ty.interp` as `[reducible]` to make sure the typeclass resolution procedure can
unfold/reduce it. For example, suppose Lean is trying to synthesize a value for the instance
`Add (Ty.interp Ty.int)`. Since `Ty.interp` is marked as `[reducible]`,
the typeclass resolution procedure can reduce `Ty.interp Ty.int` to `Int`, and use
the builtin instance for `Add Int` as the solution.
-/
@[reducible] def Ty.interp : Ty Type
| int => Int
| bool => Bool
| fn a r => a.interp r.interp
/-!
Expressions are indexed by the types of the local variables, and the type of the expression itself.
-/
inductive HasType : Fin n Vector Ty n Ty Type where
| stop : HasType 0 (ty :: ctx) ty
| pop : HasType k ctx ty HasType k.succ (u :: ctx) ty
inductive Expr : Vector Ty n Ty Type where
| var : HasType i ctx ty Expr ctx ty
| val : Int Expr ctx Ty.int
| lam : Expr (a :: ctx) ty Expr ctx (Ty.fn a ty)
| app : Expr ctx (Ty.fn a ty) Expr ctx a Expr ctx ty
| op : (a.interp b.interp c.interp) Expr ctx a Expr ctx b Expr ctx c
| ife : Expr ctx Ty.bool Expr ctx a Expr ctx a Expr ctx a
| delay : (Unit Expr ctx a) Expr ctx a
/-!
We use the command `open` to create the aliases `stop` and `pop` for `HasType.stop` and `HasType.pop` respectively.
-/
open HasType (stop pop)
/-!
Since expressions are indexed by their type, we can read the typing rules of the language from the definitions of the constructors.
Let us look at each constructor in turn.
We use a nameless representation for variables — they are de Bruijn indexed.
Variables are represented by a proof of their membership in the context, `HasType i ctx ty`,
which is a proof that variable `i` in context `ctx` has type `ty`.
We can treat `stop` as a proof that the most recently defined variable is well-typed,
and `pop n` as a proof that, if the `n`th most recently defined variable is well-typed, so is the `n+1`th.
In practice, this means we use `stop` to refer to the most recently defined variable,
`pop stop` to refer to the next, and so on, via the `Expr.var` constructor.
A value `Expr.val` carries a concrete representation of an integer.
A lambda `Expr.lam` creates a function. In the scope of a function ot type `Ty.fn a ty`, there is a
new local variable of type `a`.
A function application `Expr.app` produces a value of type `ty` given a function from `a` to `ty` and a value of type `a`.
The constructor `Expr.op` allows us to use arbitrary binary operators, where the type of the operator informs what the types of the arguments must be.
Finally, the constructor `Exp.ife` represents a `if-then-else` expression. The condition is a Boolean, and each branch must have the same type.
The auxiliary constructor `Expr.delay` is used to delay evaluation.
-/
/-!
When we evaluate an `Expr`, well need to know the values in scope, as well as their types. `Env` is an environment,
indexed over the types in scope. Since an environment is just another form of list, albeit with a strongly specified connection
to the vector of local variable types, we overload again the notation `::` so that we can use the usual list syntax.
Given a proof that a variable is defined in the context, we can then produce a value from the environment.
-/
inductive Env : Vector Ty n Type where
| nil : Env Vector.nil
| cons : Ty.interp a Env ctx Env (a :: ctx)
infix:67 " :: " => Env.cons
def Env.lookup : HasType i ctx ty Env ctx ty.interp
| stop, x :: xs => x
| pop k, x :: xs => lookup k xs
/-!
Given this, an interpreter is a function which translates an `Expr` into a Lean value with respect to a specific environment.
-/
def Expr.interp (env : Env ctx) : Expr ctx ty ty.interp
| var i => env.lookup i
| val x => x
| lam b => fun x => b.interp (Env.cons x env)
| app f a => f.interp env (a.interp env)
| op o x y => o (x.interp env) (y.interp env)
| ife c t e => if c.interp env then t.interp env else e.interp env
| delay a => (a ()).interp env
open Expr
/-!
We can make some simple test functions. Firstly, adding two inputs `fun x y => y + x` is written as follows.
-/
def add : Expr ctx (Ty.fn Ty.int (Ty.fn Ty.int Ty.int)) :=
lam (lam (op (·+·) (var stop) (var (pop stop))))
#eval add.interp Env.nil 10 20
/-!
More interestingly, a factorial function fact (e.g. `fun x => if (x == 0) then 1 else (fact (x-1) * x)`), can be written as.
Note that this is a recursive (non-terminating) definition. For every input value, the interpreter terminates, but the
definition itself is non-terminating. We use two tricks to make sure Lean accepts it. First, we use the auxiliary constructor
`Expr.delay` to delay its unfolding. Second, we add the annotation `decreasing_by sorry` which can be viwed as
"trust me, this recursive definition makes sense". Recall that `sorry` is an unsound axiom in Lean.
-/
def fact : Expr ctx (Ty.fn Ty.int Ty.int) :=
lam (ife (op (·==·) (var stop) (val 0))
(val 1)
(op (·*·) (delay fun _ => app fact (op (·-·) (var stop) (val 1))) (var stop)))
decreasing_by sorry
#eval fact.interp Env.nil 10

View File

@@ -0,0 +1,5 @@
(this example is rendered by Alectryon in the CI)
```lean
{{#include interp.lean}}
```

View File

@@ -0,0 +1,122 @@
/-!
# Palindromes
Palindromes are lists that read the same from left to right and from right to left.
For example, `[a, b, b, a]` and `[a, h, a]` are palindromes.
We use an inductive predicate to specify whether a list is a palindrome or not.
Recall that inductive predicates, or inductively defined propositions, are a convenient
way to specify functions of type `... → Prop`.
This example is a based on an example from the book "The Hitchhiker's Guide to Logical Verification".
-/
inductive Palindrome : List α Prop where
| nil : Palindrome []
| single : (a : α) Palindrome [a]
| sandwich : (a : α) Palindrome as Palindrome ([a] ++ as ++ [a])
/-!
The definition distinguishes three cases: (1) `[]` is a palindrome; (2) for any element
`a`, the singleton list `[a]` is a palindrome; (3) for any element `a` and any palindrome
`[b₁, . . ., bₙ]`, the list `[a, b₁, . . ., bₙ, a]` is a palindrome.
-/
/-!
We now prove that the reverse of a palindrome is a palindrome using induction on the inductive predicate `h : Palindrome as`.
-/
theorem palindrome_reverse (h : Palindrome as) : Palindrome as.reverse := by
induction h with
| nil => exact Palindrome.nil
| single a => exact Palindrome.single a
| sandwich a h ih => simp; exact Palindrome.sandwich _ ih
/-! If a list `as` is a palindrome, then the reverse of `as` is equal to itself. -/
theorem reverse_eq_of_palindrome (h : Palindrome as) : as.reverse = as := by
induction h with
| nil => rfl
| single a => rfl
| sandwich a h ih => simp [ih]
/-! Note that you can also easily prove `palindrome_reverse` using `reverse_eq_of_palindrome`. -/
example (h : Palindrome as) : Palindrome as.reverse := by
simp [reverse_eq_of_palindrome h, h]
/-!
Given a nonempty list, the function `List.last` returns its element.
Note that we use `(by simp)` to prove that `a₂ :: as ≠ []` in the recursive application.
-/
def List.last : (as : List α) as [] α
| [a], _ => a
| _::a₂:: as, _ => (a₂::as).last (by simp)
/-!
We use the function `List.last` to prove the following theorem that says that if a list `as` is not empty,
then removing the last element from `as` and appending it back is equal to `as`.
We use the attribute `@[simp]` to instruct the `simp` tactic to use this theorem as a simplification rule.
-/
@[simp] theorem List.dropLast_append_last (h : as []) : as.dropLast ++ [as.last h] = as := by
match as with
| [] => contradiction
| [a] => simp_all [last, dropLast]
| a₁ :: a₂ :: as =>
simp [last, dropLast]
exact dropLast_append_last (as := a₂ :: as) (by simp)
/-!
We now define the following auxiliary induction principle for lists using well-founded recursion on `as.length`.
We can read it as follows, to prove `motive as`, it suffices to show that: (1) `motive []`; (2) `motive [a]` for any `a`;
(3) if `motive as` holds, then `motive ([a] ++ as ++ [b])` also holds for any `a`, `b`, and `as`.
Note that the structure of this induction principle is very similar to the `Palindrome` inductive predicate.
-/
theorem List.palindrome_ind (motive : List α Prop)
(h₁ : motive [])
(h₂ : (a : α) motive [a])
(h₃ : (a b : α) (as : List α) motive as motive ([a] ++ as ++ [b]))
(as : List α)
: motive as :=
match as with
| [] => h₁
| [a] => h₂ a
| a₁::a₂::as' =>
have ih := palindrome_ind motive h₁ h₂ h₃ (a₂::as').dropLast
have : [a₁] ++ (a₂::as').dropLast ++ [(a₂::as').last (by simp)] = a₁::a₂::as' := by simp
this h₃ _ _ _ ih
termination_by _ as => as.length
/-!
We use our new induction principle to prove that if `as.reverse = as`, then `Palindrome as` holds.
Note that we use the `using` modifier to instruct the `induction` tactic to use this induction principle
instead of the default one for lists.
-/
theorem List.palindrome_of_eq_reverse (h : as.reverse = as) : Palindrome as := by
induction as using palindrome_ind
next => exact Palindrome.nil
next a => exact Palindrome.single a
next a b as ih =>
have : a = b := by simp_all
subst this
have : as.reverse = as := by simp_all
exact Palindrome.sandwich a (ih this)
/-!
We now define a function that returns `true` iff `as` is a palindrome.
The function assumes that the type `α` has decidable equality. We need this assumption
because we need to compare the list elements.
-/
def List.isPalindrome [DecidableEq α] (as : List α) : Bool :=
as.reverse = as
/-!
It is straightforward to prove that `isPalindrome` is correct using the previously proved theorems.
-/
theorem List.isPalindrome_correct [DecidableEq α] (as : List α) : as.isPalindrome Palindrome as := by
simp [isPalindrome]
exact Iff.intro (fun h => palindrome_of_eq_reverse h) (fun h => reverse_eq_of_palindrome h)
#eval [1, 2, 1].isPalindrome
#eval [1, 2, 3, 1].isPalindrome
example : [1, 2, 1].isPalindrome := rfl
example : [1, 2, 2, 1].isPalindrome := rfl
example : ![1, 2, 3, 1].isPalindrome := rfl

View File

@@ -0,0 +1,5 @@
(this example is rendered by Alectryon in the CI)
```lean
{{#include palindromes.lean}}
```

239
doc/examples/phoas.lean Normal file
View File

@@ -0,0 +1,239 @@
/-!
# Parametric Higher-Order Abstract Syntax
In contrast to first-order encodings, higher-order encodings avoid explicit modeling of variable identity.
Instead, the binding constructs of an object language (the language being
formalized) can be represented using the binding constructs of the meta language (the language in which the formalization is done).
The best known higher-order encoding is called higher-order abstract syntax (HOAS),
and we can start by attempting to apply it directly in Lean.
Remark: this example is based on an example in the book [Certified Programming with Dependent Types](http://adam.chlipala.net/cpdt/) by Adam Chlipala.
-/
/-!
Here is the definition of the simple type system for our programming language, a simply typed
lambda calculus with natural numbers as the base type.
-/
inductive Ty where
| nat
| fn : Ty Ty Ty
/-!
We can write a function to translate `Ty` values to a Lean type
— remember that types are first class, so can be calculated just like any other value.
We mark `Ty.denote` as `[reducible]` to make sure the typeclass resolution procedure can
unfold/reduce it. For example, suppose Lean is trying to synthesize a value for the instance
`Add (Ty.denote Ty.nat)`. Since `Ty.denote` is marked as `[reducible]`,
the typeclass resolution procedure can reduce `Ty.denote Ty.nat` to `Nat`, and use
the builtin instance for `Add Nat` as the solution.
Recall that the term `a.denote` is sugar for `denote a` where `denote` is the function being defined.
We call it the "dot notation".
-/
@[reducible] def Ty.denote : Ty Type
| nat => Nat
| fn a b => a.denote b.denote
/-!
With HOAS, each object language binding construct is represented with a function of
the meta language. Here is what we get if we apply that idea within an inductive definition
of term syntax. However a naive encondig in Lean fails to meet the strict positivity restrictions
imposed by the Lean kernel. An alternate higher-order encoding is parametric HOAS, as introduced by Washburn
and Weirich for Haskell and tweaked by Adam Chlipala for use in Coq. The key idea is to parameterize the
declaration by a type family `rep` standing for a "representation of variables."
-/
inductive Term' (rep : Ty Type) : Ty Type
| var : rep ty Term' rep ty
| const : Nat Term' rep .nat
| plus : Term' rep .nat Term' rep .nat Term' rep .nat
| lam : (rep dom Term' rep ran) Term' rep (.fn dom ran)
| app : Term' rep (.fn dom ran) Term' rep dom Term' rep ran
| let : Term' rep ty₁ (rep ty₁ Term' rep ty₂) Term' rep ty₂
/-!
Lean accepts this definition because our embedded functions now merely take variables as
arguments, instead of arbitrary terms. One might wonder whether there is an easy loophole
to exploit here, instantiating the parameter `rep` as term itself. However, to do that, we
would need to choose a variable representation for this nested mention of term, and so on
through an infinite descent into term arguments.
We write the final type of a closed term using polymorphic quantification over all possible
choices of `rep` type family
-/
open Ty (nat fn)
namespace FirstTry
def Term (ty : Ty) := (rep : Ty Type) Term' rep ty
/-!
In the next two example, note how each is written as a function over a `rep` choice,
such that the specific choice has no impact on the structure of the term.
-/
def add : Term (fn nat (fn nat nat)) := fun _rep =>
.lam fun x => .lam fun y => .plus (.var x) (.var y)
def three_the_hard_way : Term nat := fun rep =>
.app (.app (add rep) (.const 1)) (.const 2)
end FirstTry
/-!
The argument `rep` does not even appear in the function body for `add`. How can that be?
By giving our terms expressive types, we allow Lean to infer many arguments for us. In fact,
we do not even need to name the `rep` argument! By using Lean implicit arguments and lambdas,
we can completely hide `rep` in these examples.
-/
def Term (ty : Ty) := {rep : Ty Type} Term' rep ty
def add : Term (fn nat (fn nat nat)) :=
.lam fun x => .lam fun y => .plus (.var x) (.var y)
def three_the_hard_way : Term nat :=
.app (.app add (.const 1)) (.const 2)
/-!
It may not be at all obvious that the PHOAS representation admits the crucial computable
operations. The key to effective deconstruction of PHOAS terms is one principle: treat
the `rep` parameter as an unconstrained choice of which data should be annotated on each
variable. We will begin with a simple example, that of counting how many variable nodes
appear in a PHOAS term. This operation requires no data annotated on variables, so we
simply annotate variables with `Unit` values. Note that, when we go under binders in the
cases for `lam` and `let`, we must provide the data value to annotate on the new variable we
pass beneath. For our current choice of `Unit` data, we always pass `()`.
-/
def countVars : Term' (fun _ => Unit) ty Nat
| .var _ => 1
| .const _ => 0
| .plus a b => countVars a + countVars b
| .app f a => countVars f + countVars a
| .lam b => countVars (b ())
| .let a b => countVars a + countVars (b ())
/-! We can now easily prove that `add` has two variables by using reflexivity -/
example : countVars add = 2 :=
rfl
/-!
Here is another example, translating PHOAS terms into strings giving a first-order rendering.
To implement this translation, the key insight is to tag variables with strings, giving their names.
The function takes as an additional input `i` which is used to create variable names for binders.
We also use the string interpolation available in Lean. For example, `s!"x_{i}"` is expanded to
`"x_" ++ toString i`.
-/
def pretty (e : Term' (fun _ => String) ty) (i : Nat := 1) : String :=
match e with
| .var s => s
| .const n => toString n
| .app f a => s!"({pretty f i} {pretty a i})"
| .plus a b => s!"({pretty a i} + {pretty b i})"
| .lam f =>
let x := s!"x_{i}"
s!"(fun {x} => {pretty (f x) (i+1)})"
| .let a b =>
let x := s!"x_{i}"
s!"(let {x} := {pretty a i}; => {pretty (b x) (i+1)}"
#eval pretty three_the_hard_way
/-!
It is not necessary to convert to a different representation to support many common
operations on terms. For instance, we can implement substitution of terms for variables.
The key insight here is to tag variables with terms, so that, on encountering a variable, we
can simply replace it by the term in its tag. We will call this function initially on a term
with exactly one free variable, tagged with the appropriate substitute. During recursion,
new variables are added, but they are only tagged with their own term equivalents. Note
that this function squash is parameterized over a specific `rep` choice.
-/
def squash : Term' (Term' rep) ty Term' rep ty
| .var e => e
| .const n => .const n
| .plus a b => .plus (squash a) (squash b)
| .lam f => .lam fun x => squash (f (.var x))
| .app f a => .app (squash f) (squash a)
| .let a b => .let (squash a) fun x => squash (b (.var x))
/-!
To define the final substitution function over terms with single free variables, we define
`Term1`, an analogue to Term that we defined before for closed terms.
-/
def Term1 (ty1 ty2 : Ty) := {rep : Ty Type} rep ty1 Term' rep ty2
/-!
Substitution is defined by (1) instantiating a `Term1` to tag variables with terms and (2)
applying the result to a specific term to be substituted. Note how the parameter `rep` of
`squash` is instantiated: the body of `subst` is itself a polymorphic quantification over `rep`,
standing for a variable tag choice in the output term; and we use that input to compute a
tag choice for the input term.
-/
def subst (e : Term1 ty1 ty2) (e' : Term ty1) : Term ty2 :=
squash (e e')
/-!
We can view `Term1` as a term with hole. In the following example,
`(fun x => plus (var x) (const 5))` can be viewed as the term `plus _ (const 5)` where
the hole `_` is instantiated by `subst` with `three_the_hard_way`
-/
#eval pretty <| subst (fun x => .plus (.var x) (.const 5)) three_the_hard_way
/-!
One further development, which may seem surprising at first,
is that we can also implement a usual term denotation function,
when we tag variables with their denotations.
The attribute `[simp]` instructs Lean to always try to unfold `denote` applications when one applies
the `simp` tactic. We also say this is a hint for the Lean term simplifier.
-/
@[simp] def denote : Term' Ty.denote ty ty.denote
| .var x => x
| .const n => n
| .plus a b => denote a + denote b
| .app f a => denote f (denote a)
| .lam f => fun x => denote (f x)
| .let a b => denote (b (denote a))
example : denote three_the_hard_way = 3 :=
rfl
/-!
To summarize, the PHOAS representation has all the expressive power of more
standard encodings (e.g., using de Bruijn indices), and a variety of translations are actually much more pleasant to
implement than usual, thanks to the novel ability to tag variables with data.
-/
/-!
We now define the constant folding optimization that traverses a term if replaces subterms such as
`plus (const m) (const n)` with `const (n+m)`.
-/
@[simp] def constFold : Term' rep ty Term' rep ty
| .var x => .var x
| .const n => .const n
| .app f a => .app (constFold f) (constFold a)
| .lam f => .lam fun x => constFold (f x)
| .let a b => .let (constFold a) fun x => constFold (b x)
| .plus a b =>
match constFold a, constFold b with
| .const n, .const m => .const (n+m)
| a', b' => .plus a' b'
/-!
The correctness of the `constFold` is proved using induction, case-analysis, and the term simplifier.
We prove all cases but the one for `plus` using `simp [*]`. This tactic instructs the term simplifier to
use hypotheses such as `a = b` as rewriting/simplications rules.
We use the `split` to break the nested `match` expression in the `plus` case into two cases.
The local variables `iha` and `ihb` are the induction hypotheses for `a` and `b`.
The modifier `←` in a term simplifier argument instructs the term simplier to use the equation as a rewriting rule in
the "reverse direction. That is, given `h : a = b`, `← h` instructs the term simplifier to rewrite `b` subterms to `a`.
-/
theorem constFold_sound (e : Term' Ty.denote ty) : denote (constFold e) = denote e := by
induction e with simp [*]
| plus a b iha ihb =>
split
next he₁ he₂ => simp [ iha, ihb, he₁, he₂]
next => simp [iha, ihb]

View File

@@ -0,0 +1,5 @@
(this example is rendered by Alectryon in the CI)
```lean
{{#include phoas.lean}}
```

119
doc/examples/tc.lean Normal file
View File

@@ -0,0 +1,119 @@
/-!
# A Certified Type Checker
In this example, we build a certified type checker for a simple expression
language.
Remark: this example is based on an example in the book [Certified Programming with Dependent Types](http://adam.chlipala.net/cpdt/) by Adam Chlipala.
-/
inductive Expr where
| nat : Nat Expr
| plus : Expr Expr Expr
| bool : Bool Expr
| and : Expr Expr Expr
/-!
We define a simple language of types using the inductive datatype `Ty`, and
its typing rules using the inductive predicate `HasType`.
-/
inductive Ty where
| nat
| bool
deriving DecidableEq
inductive HasType : Expr Ty Prop
| nat : HasType (.nat v) .nat
| plus : HasType a .nat HasType b .nat HasType (.plus a b) .nat
| bool : HasType (.bool v) .bool
| and : HasType a .bool HasType b .bool HasType (.and a b) .bool
/-!
We can easily show that if `e` has type `t₁` and type `t₂`, then `t₁` and `t₂` must be equal
by using the the `cases` tactic. This tactic creates a new subgoal for every constructor,
and automatically discharges unreachable cases. The tactic combinator `tac₁ <;> tac₂` applies
`tac₂` to each subgoal produced by `tac₁`. Then, the tactic `rfl` is used to close all produced
goals using reflexivity.
-/
theorem HasType.det (h₁ : HasType e t₁) (h₂ : HasType e t₂) : t₁ = t₂ := by
cases h₁ <;> cases h₂ <;> rfl
/-!
The inductive type `Maybe p` has two contructors: `found a h` and `unknown`.
The former contains an element `a : α` and a proof that `a` satisfies the predicate `p`.
The constructor `unknown` is used to encode "failure".
-/
inductive Maybe (p : α Prop) where
| found : (a : α) p a Maybe p
| unknown
/-!
We define a notation for `Maybe` that is similar to the builtin notation for the Lean builtin type `Subtype`.
-/
notation "{{ " x " | " p " }}" => Maybe (fun x => p)
/-!
The function `Expr.typeCheck e` returns a type `ty` and a proof that `e` has type `ty`,
or `unknown`.
Recall that, `def Expr.typeCheck ...` in Lean is notation for `namespace Expr def typeCheck ... end Expr`.
The term `.found .nat .nat` is sugar for `Maybe.found Ty.nat HasType.nat`. Lean can infer the namespaces using
the expected types.
-/
def Expr.typeCheck (e : Expr) : {{ ty | HasType e ty }} :=
match e with
| nat .. => .found .nat .nat
| bool .. => .found .bool .bool
| plus a b =>
match a.typeCheck, b.typeCheck with
| .found .nat h₁, .found .nat h₂ => .found .nat (.plus h₁ h₂)
| _, _ => .unknown
| and a b =>
match a.typeCheck, b.typeCheck with
| .found .bool h₁, .found .bool h₂ => .found .bool (.and h₁ h₂)
| _, _ => .unknown
theorem Expr.typeCheck_correct (h₁ : HasType e ty) (h₂ : e.typeCheck .unknown)
: e.typeCheck = .found ty h := by
revert h₂
cases typeCheck e with
| found ty' h' => intro; have := HasType.det h₁ h'; subst this; rfl
| unknown => intros; contradiction
/-!
Now, we prove that if `Expr.typeCheck e` returns `Maybe.unknown`, then forall `ty`, `HasType e ty` does not hold.
The notation `e.typeCheck` is sugar for `Expr.typeCheck e`. Lean can infer this because we explicitly said that `e` has type `Expr`.
The proof is by induction on `e` and case analysis. The tactic `rename_i` is used to to rename "inaccessible" variables.
We say a variable is inaccessible if it is introduced by a tactic (e.g., `cases`) or has been shadowed by another variable introduced
by the user. Note that the tactic `simp [typeCheck]` is applied to all goal generated by the `induction` tactic, and closes
the cases corresponding to the constructors `Expr.nat` and `Expr.bool`.
-/
theorem Expr.typeCheck_complete {e : Expr} : e.typeCheck = .unknown ¬ HasType e ty := by
induction e with simp [typeCheck]
| plus a b iha ihb =>
split
next => intros; contradiction
next ra rb hnp =>
-- Recall that `hnp` is a hypothesis generated by the `split` tactic
-- that asserts the previous case was not taken
intro h ht
cases ht with
| plus h₁ h₂ => exact hnp h₁ h₂ (typeCheck_correct h₁ (iha · h₁)) (typeCheck_correct h₂ (ihb · h₂))
| and a b iha ihb =>
split
next => intros; contradiction
next ra rb hnp =>
intro h ht
cases ht with
| and h₁ h₂ => exact hnp h₁ h₂ (typeCheck_correct h₁ (iha · h₁)) (typeCheck_correct h₂ (ihb · h₂))
/-!
Finally, we show that type checking for `e` can be decided using `Expr.typeCheck`.
-/
instance (e : Expr) (t : Ty) : Decidable (HasType e t) :=
match h' : e.typeCheck with
| .found t' ht' =>
if heq : t = t' then
isTrue (heq ht')
else
isFalse fun ht => heq (HasType.det ht ht')
| .unknown => isFalse (Expr.typeCheck_complete h')

5
doc/examples/tc.lean.md Normal file
View File

@@ -0,0 +1,5 @@
(this example is rendered by Alectryon in the CI)
```lean
{{#include tc.lean}}
```

4
doc/examples/test_single.sh Executable file
View File

@@ -0,0 +1,4 @@
#!/usr/bin/env bash
source ../../tests/common.sh
exec_check lean -j 0 -Dlinter.all=false "$f"

186
doc/examples/widgets.lean Normal file
View File

@@ -0,0 +1,186 @@
import Lean
open Lean Widget
/-!
# The user-widgets system
Proving and programming are inherently interactive tasks. Lots of mathematical objects and data
structures are visual in nature. *User widgets* let you associate custom interactive UIs with
sections of a Lean document. User widgets are rendered in the Lean infoview.
![Rubik's cube](../images/widgets_rubiks.png)
## Trying it out
To try it out, simply type in the following code and place your cursor over the `#widget` command.
-/
@[widget]
def helloWidget : UserWidgetDefinition where
name := "Hello"
javascript := "
import * as React from 'react';
export default function(props) {
const name = props.name || 'world'
return React.createElement('p', {}, name + '!')
}"
#widget helloWidget .null
/-!
If you want to dive into a full sample right away, check out
[`RubiksCube`](https://github.com/leanprover/lean4-samples/blob/main/RubiksCube/).
Below, we'll explain the system piece by piece.
⚠️ WARNING: All of the user widget APIs are **unstable** and subject to breaking changes.
## Widget sources and instances
A *widget source* is a valid JavaScript [ESModule](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules)
which exports a [React component](https://reactjs.org/docs/components-and-props.html). To access
React, the module must use `import * as React from 'react'`. Our first example of a widget source
is of course the value of `helloWidget.javascript`.
We can register a widget source with the `@[widget]` attribute, giving it a friendlier name
in the `name` field. This is bundled together in a `UserWidgetDefinition`.
A *widget instance* is then the identifier of a `UserWidgetDefinition` (so `` `helloWidget ``,
not `"Hello"`) associated with a range of positions in the Lean source code. Widget instances
are stored in the *infotree* in the same manner as other information about the source file
such as the type of every expression. In our example, the `#widget` command stores a widget instance
with the entire line as its range. We can think of a widget instance as an instruction for the
infoview: "when the user places their cursor here, please render the following widget".
Every widget instance also contains a `props : Json` value. This value is passed as an argument
to the React component. In our first invocation of `#widget`, we set it to `.null`. Try out what
happens when you type in:
-/
#widget helloWidget (Json.mkObj [("name", "<your name here>")])
/-!
💡 NOTE: The RPC system presented below does not depend on JavaScript. However the primary use case
is the web-based infoview in VSCode.
## Querying the Lean server
Besides enabling us to create cool client-side visualizations, user widgets come with the ability
to communicate with the Lean server. Thanks to this, they have the same metaprogramming capabilities
as custom elaborators or the tactic framework. To see this in action, let's implement a `#check`
command as a web input form. This example assumes some familiarity with React.
The first thing we'll need is to create an *RPC method*. Meaning "Remote Procedure Call", this
is basically a Lean function callable from widget code (possibly remotely over the internet).
Our method will take in the `name : Name` of a constant in the environment and return its type.
By convention, we represent the input data as a `structure`. Since it will be sent over from JavaScript,
we need `FromJson` and `ToJson`. We'll see below why the position field is needed.
-/
structure GetTypeParams where
/-- Name of a constant to get the type of. -/
name : Name
/-- Position of our widget instance in the Lean file. -/
pos : Lsp.Position
deriving FromJson, ToJson
/-!
After its arguments, we define the `getType` method. Every RPC method executes in the `RequestM`
monad and must return a `RequestTask α` where `α` is its "actual" return type. The `Task` is so
that requests can be handled concurrently. A first guess for `α` might be `Expr`. However,
expressions in general can be large objects which depend on an `Environment` and `LocalContext`.
Thus we cannot directly serialize an `Expr` and send it to the widget. Instead, there are two
options:
- One is to send a *reference* which points to an object residing on the server. From JavaScript's
point of view, references are entirely opaque, but they can be sent back to other RPC methods for
further processing.
- Two is to pretty-print the expression and send its textual representation called `CodeWithInfos`.
This representation contains extra data which the infoview uses for interactivity. We take this
strategy here.
RPC methods execute in the context of a file, but not any particular `Environment` so they don't
know about the available `def`initions and `theorem`s. Thus, we need to pass in a position at which
we want to use the local `Environment`. This is why we store it in `GetTypeParams`. The `withWaitFindSnapAtPos`
method launches a concurrent computation whose job is to find such an `Environment` and a bit
more information for us, in the form of a `snap : Snapshot`. With this in hand, we can call
`MetaM` procedures to find out the type of `name` and pretty-print it.
-/
open Server RequestM in
@[serverRpcMethod]
def getType (params : GetTypeParams) : RequestM (RequestTask CodeWithInfos) :=
withWaitFindSnapAtPos params.pos fun snap => do
runTermElabM snap do
let name resolveGlobalConstNoOverloadCore params.name
let some c Meta.getConst? name
| throwThe RequestError .invalidParams, s!"no constant named '{name}'"
Widget.ppExprTagged c.type
/-!
## Using infoview components
Now that we have all we need on the server side, let's write the widget source. By importing
`@leanprover/infoview`, widgets can render UI components used to implement the infoview itself.
For example, the `<InteractiveCode>` component displays expressions with `term : type` tooltips
as seen in the goal view. We will use it to implement our custom `#check` display.
⚠️ WARNING: Like the other widget APIs, the infoview JS API is **unstable** and subject to breaking changes.
The code below demonstrates useful parts of the API. To make RPC method calls, we use the `RpcContext`.
The `useAsync` helper packs the results of a call into a `status` enum, the returned `val`ue in case
the call was successful, and otherwise an `err`or. Based on the `status` we either display
an `InteractiveCode`, or `mapRpcError` the error in order to turn it into a readable message.
-/
@[widget]
def checkWidget : UserWidgetDefinition where
name := "#check as a service"
javascript := "
import * as React from 'react';
const e = React.createElement;
import { RpcContext, InteractiveCode, useAsync, mapRpcError } from '@leanprover/infoview';
export default function(props) {
const rs = React.useContext(RpcContext)
const [name, setName] = React.useState('getType')
const [status, val, err] = useAsync(() =>
rs.call('getType', { name, pos: props.pos }), [name, rs, props.pos])
const type = status === 'fulfilled' ? val && e(InteractiveCode, {fmt: val})
: status === 'rejected' ? e('p', null, mapRpcError(err).message)
: e('p', null, 'Loading..')
const onChange = (event) => { setName(event.target.value) }
return e('div', null,
e('input', { value: name, onChange }),
' : ',
type)
}
"
/-!
Finally we can try out the widget.
-/
#widget checkWidget .null
/-!
![`#check` as a service](../images/widgets_caas.png)
## Building widget sources
While typing JavaScript inline is fine for a simple example, for real developments we want to use
packages from NPM, a proper build system, and JSX. Thus, most actual widget sources are built with
Lake and NPM. They consist of multiple files and may import libraries which don't work as ESModules
by default. On the other hand a widget source must be a single, self-contained ESModule in the form
of a string. Readers familiar with web development may already have guessed that to obtain such a
string, we need a *bundler*. Two popular choices are [`rollup.js`](https://rollupjs.org/guide/en/)
and [`esbuild`](https://esbuild.github.io/). If we go with `rollup.js`, to make a widget work with
the infoview we need to:
- Set [`output.format`](https://rollupjs.org/guide/en/#outputformat) to `'es'`.
- [Externalize](https://rollupjs.org/guide/en/#external) `react`, `react-dom`, `@leanprover/infoview`.
These libraries are already loaded by the infoview so they should not be bundled.
In the RubiksCube sample, we provide a working `rollup.js` build configuration in
[rollup.config.js](https://github.com/leanprover/lean4-samples/blob/main/RubiksCube/widget/rollup.config.js).
-/

View File

@@ -0,0 +1,5 @@
(this chapter is rendered by Alectryon in the CI)
```lean
{{#include widgets.lean}}
```

View File

@@ -219,10 +219,10 @@ def f2 (a b c : Bool) : Bool :=
#eval (1, 2)
def p : Nat × Bool := (1,
def p : Nat × Bool := (1, false)
section
variables (a b c : Nat) (p : Nat × bool)
variable (a b c : Nat) (p : Nat × bool)
#check (1, 2)
#check p.1 * 2
@@ -232,8 +232,8 @@ end
/- lists -/
section
variables x y z : Nat
variables xs ys zs : list Nat
variable x y z : Nat
variable xs ys zs : list Nat
open list
#check (1 :: xs) ++ (y :: zs) ++ [1,2,3]
@@ -243,7 +243,7 @@ end
/- sets -/
section
variables s t u : set Nat
variable s t u : set Nat
#check ({1, 2, 3} ∩ s) ({x | x < 7} ∩ t)
end
@@ -276,7 +276,7 @@ Finally, for data types with one constructor, one destruct an element by pattern
.. code-block:: lean
universes u v
variables {α : Type u} {β : Type v}
variable {α : Type u} {β : Type v}
def p : Nat × := ⟨1, 2⟩
#check p.fst
@@ -369,7 +369,7 @@ Here is an example:
.. code-block:: lean
variables (a b c d e : Nat)
variable (a b c d e : Nat)
variable h1 : a = b
variable h2 : b = c + 1
variable h3 : c = d
@@ -419,33 +419,31 @@ Every computable definition in Lean is compiled to bytecode at definition time.
.. code-block:: lean
#reduce (λ x, x + 3) 5
#eval (λ x, x + 3) 5
#reduce (fun x => x + 3) 5
#eval (fun x => x + 3) 5
#reduce let x := 5 in x + 3
#eval let x := 5 in x + 3
#reduce let x := 5; x + 3
#eval let x := 5; x + 3
def f x := x + 3
#reduce f 5
#eval f 5
#reduce @nat.rec (λ n, Nat) (0 : Nat)
(λ n recval : Nat, recval + n + 1) (5 : Nat)
#eval @nat.rec (λ n, Nat) (0 : Nat)
(λ n recval : Nat, recval + n + 1) (5 : Nat)
#reduce @Nat.rec (λ n => Nat) (0 : Nat)
(λ n recval : Nat => recval + n + 1) (5 : Nat)
def g : Nat → Nat
| 0 := 0
| (n+1) := g n + n + 1
| 0 => 0
| (n+1) => g n + n + 1
#reduce g 5
#eval g 5
#eval g 50000
#eval g 5000
example : (λ x, x + 3) 5 = 8 := rfl
example : (λ x, f x) = f := rfl
example : (fun x => x + 3) 5 = 8 := rfl
example : (fun x => f x) = f := rfl
example (p : Prop) (h₁ h₂ : p) : h₁ = h₂ := rfl
Note: the combination of proof irrelevance and singleton ``Prop`` elimination in ι-reduction renders the ideal version of definitional equality, as described above, undecidable. Lean's procedure for checking definitional equality is only an approximation to the ideal. It is not transitive, as illustrated by the example below. Once again, this does not compromise the consistency or soundness of Lean; it only means that Lean is more conservative in the terms it recognizes as well typed, and this does not cause problems in practice. Singleton elimination will be discussed in greater detail in [Inductive Types](inductive.md).

214
doc/flake.lock generated Normal file
View File

@@ -0,0 +1,214 @@
{
"nodes": {
"alectryon": {
"flake": false,
"locked": {
"lastModified": 1654613606,
"narHash": "sha256-IGCn1PzTyw8rrwmyWUiw3Jo/dyZVGkMslnHYW7YB8yk=",
"owner": "Kha",
"repo": "alectryon",
"rev": "c3b16f650665745e1da4ddfcc048d3bd639f71d5",
"type": "github"
},
"original": {
"owner": "Kha",
"ref": "typeid",
"repo": "alectryon",
"type": "github"
}
},
"flake-utils": {
"locked": {
"lastModified": 1644229661,
"narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"lean": {
"inputs": {
"flake-utils": "flake-utils",
"lean-stage0": "lean-stage0",
"lean4-mode": "lean4-mode",
"nix": "nix",
"nixpkgs": "nixpkgs_2"
},
"locked": {
"lastModified": 0,
"narHash": "sha256-AfBkKX6Ahb9YbZke+eWLmsUk1Z9BwdJ1CpIoPY8Msx8=",
"path": "../.",
"type": "path"
},
"original": {
"path": "../.",
"type": "path"
}
},
"lean-stage0": {
"locked": {
"lastModified": 0,
"narHash": "sha256-3K/43lSW4WIHNG+HHVKCD1odS63mHuaQ4ueHyTIkcls=",
"owner": "leanprover",
"repo": "lean4",
"rev": "0000000000000000000000000000000000000000",
"type": "github"
},
"original": {
"owner": "leanprover",
"repo": "lean4",
"type": "github"
}
},
"lean4-mode": {
"flake": false,
"locked": {
"lastModified": 1647694750,
"narHash": "sha256-0rV61KhevG9IAjZDN2Ts2VS65fiUAPAezbf282u7yy8=",
"owner": "leanprover",
"repo": "lean4-mode",
"rev": "c016c7aeee92564836355083664c49ed57024427",
"type": "github"
},
"original": {
"owner": "leanprover",
"repo": "lean4-mode",
"type": "github"
}
},
"leanInk": {
"flake": false,
"locked": {
"lastModified": 1656863690,
"narHash": "sha256-9tmynTTeJGhYZaltS4xhSJgLTpe7Ta1ofV6U1SA/5V4=",
"owner": "leanprover",
"repo": "LeanInk",
"rev": "4b5e606ea8cc54c2447ce48706f8ec1d133d19e9",
"type": "github"
},
"original": {
"owner": "leanprover",
"repo": "LeanInk",
"type": "github"
}
},
"lowdown-src": {
"flake": false,
"locked": {
"lastModified": 1633514407,
"narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=",
"owner": "kristapsdz",
"repo": "lowdown",
"rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8",
"type": "github"
},
"original": {
"owner": "kristapsdz",
"repo": "lowdown",
"type": "github"
}
},
"mdBook": {
"flake": false,
"locked": {
"lastModified": 1660074464,
"narHash": "sha256-W30G7AeWBjdJE/CQZJU5vJjaDGZtpmxEKNMEvaYtuF8=",
"owner": "leanprover",
"repo": "mdBook",
"rev": "9321c10c502cd59eea8afc4325a84eab3ddf9391",
"type": "github"
},
"original": {
"owner": "leanprover",
"repo": "mdBook",
"type": "github"
}
},
"nix": {
"inputs": {
"lowdown-src": "lowdown-src",
"nixpkgs": "nixpkgs",
"nixpkgs-regression": "nixpkgs-regression"
},
"locked": {
"lastModified": 1648022028,
"narHash": "sha256-HtwmifW6STPcym+3uJ4YavgTKTYVIoiQHg3f0wXOm+Q=",
"owner": "NixOS",
"repo": "nix",
"rev": "98ce1a21b7d959c5575fac566c8699e91703a9f7",
"type": "github"
},
"original": {
"owner": "NixOS",
"repo": "nix",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1632864508,
"narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "82891b5e2c2359d7e58d08849e4c89511ab94234",
"type": "github"
},
"original": {
"id": "nixpkgs",
"ref": "nixos-21.05-small",
"type": "indirect"
}
},
"nixpkgs-regression": {
"locked": {
"lastModified": 1643052045,
"narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
"type": "github"
},
"original": {
"id": "nixpkgs",
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
"type": "indirect"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1648219316,
"narHash": "sha256-Ctij+dOi0ZZIfX5eMhgwugfvB+WZSrvVNAyAuANOsnQ=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "30d3d79b7d3607d56546dd2a6b49e156ba0ec634",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"alectryon": "alectryon",
"flake-utils": [
"lean",
"flake-utils"
],
"lean": "lean",
"leanInk": "leanInk",
"mdBook": "mdBook"
}
}
},
"root": "root",
"version": 7
}

101
doc/flake.nix Normal file
View File

@@ -0,0 +1,101 @@
{
description = "Lean documentation";
inputs.lean.url = path:../.;
inputs.flake-utils.follows = "lean/flake-utils";
inputs.mdBook = {
url = github:leanprover/mdBook;
flake = false;
};
inputs.alectryon = {
url = github:Kha/alectryon/typeid;
flake = false;
};
inputs.leanInk = {
url = github:leanprover/LeanInk;
flake = false;
};
outputs = inputs@{ self, ... }: inputs.flake-utils.lib.eachDefaultSystem (system:
with inputs.lean.packages.${system}; with nixpkgs;
let
doc-src = lib.sourceByRegex ../. ["doc.*" "tests(/lean(/beginEndAsMacro.lean)?)?"];
in {
packages = rec {
lean-mdbook = mdbook.overrideAttrs (drv: rec {
name = "lean-${mdbook.name}";
src = inputs.mdBook;
cargoDeps = drv.cargoDeps.overrideAttrs (_: {
inherit src;
outputHash = "sha256-mhTWHs/bsmm3FH59SkUxBTl5lEH2Rlz/aF9CuBTu1TE=";
});
doCheck = false;
});
book = stdenv.mkDerivation {
name ="lean-doc";
src = doc-src;
buildInputs = [ lean-mdbook ];
buildCommand = ''
mkdir $out
# necessary for `additional-css`...?
cp -r --no-preserve=mode $src/doc/* .
# overwrite stub .lean.md files
cp -r ${inked}/* .
mdbook build -d $out
'';
};
# We use a separate derivation instead of `checkPhase` so we can push it but not `doc` to the binary cache
test = stdenv.mkDerivation {
name ="lean-doc-test";
src = doc-src;
buildInputs = [ lean-mdbook stage1.Lean.lean-package strace ];
patchPhase = ''
cd doc
patchShebangs test
'';
buildPhase = ''
mdbook test
touch $out
'';
dontInstall = true;
};
leanInk = (buildLeanPackage {
name = "Main";
src = inputs.leanInk;
deps = [ (buildLeanPackage {
name = "LeanInk";
src = inputs.leanInk;
}) ];
executableName = "leanInk";
linkFlags = ["-rdynamic"];
}).executable;
alectryon = python3Packages.buildPythonApplication {
name = "alectryon";
src = inputs.alectryon;
propagatedBuildInputs =
[ leanInk lean-all ] ++
# https://github.com/cpitclaudel/alectryon/blob/master/setup.cfg
(with python3Packages; [ pygments dominate beautifulsoup4 docutils ]);
doCheck = false;
};
renderLean = name: file: runCommandNoCC "${name}.md" { buildInputs = [ alectryon ]; } ''
mkdir -p $(basename $out/${name})
alectryon --frontend lean4+markup ${file} --backend webpage -o $out/${name}.md
'';
listFilesRecursiveRel = root: dir: lib.flatten (lib.mapAttrsToList (name: type:
if type == "directory" then
listFilesRecursiveRel root ("${dir}/${name}")
else
dir + "/${name}"
) (builtins.readDir "${root}/${dir}"));
renderDir = dir: let
inputs = builtins.filter (n: builtins.match ".*\.lean" n != null) (listFilesRecursiveRel dir ".");
outputs = lib.genAttrs inputs (n: renderLean n "${dir}/${n}");
in
outputs // symlinkJoin { inherit name; paths = lib.attrValues outputs; };
inked = renderDir ./.;
doc = book;
};
defaultPackage = self.packages.${system}.doc;
});
}

7
doc/fplean.md Normal file
View File

@@ -0,0 +1,7 @@
Functional Programming in Lean
=======================
The goal of [this book](https://leanprover.github.io/functional_programming_in_lean/) is to be an accessible introduction to using Lean 4 as a programming language.
It should be useful both to people who want to use Lean as a general-purpose programming language and to mathematicians who want to develop larger-scale proof automation but do not have a background in functional programming.
It does not assume any background with functional programming, though it's probably not a good first book on programming in general.
New content will be added once per month until it's done.

View File

@@ -46,6 +46,25 @@ partial def g (x : Nat) (p : Nat -> Bool) : Nat :=
In the previous example, `g x p` only terminates if there is a `y >= x` such that `p y` returns `true`.
Of course, `g 0 (fun x => false)` never terminates.
However, the use of `partial` is restricted to functions whose return type is not empty so the soundness
of the system is not compromised.
```lean,ignore
partial def loop? : α := -- failed to compile partial definition 'loop?', failed to
loop? -- show that type is inhabited and non empty
partial def loop [Inhabited α] : α := -- compiles
loop
example : True := -- accepted
loop
example : False :=
loop -- failed to synthesize instance Inhabited False
```
If we were able to partially define `loop?`, we could prove `False` with it.
# Lambda expressions
A lambda expression is an unnamed function.
@@ -70,28 +89,25 @@ def twice (f : Nat -> Nat) (x : Nat) : Nat :=
# Syntax sugar for simple lambda expressions
Simple functions can be defined using parentheses and `.` (or `·`) as a placeholder.
Simple functions can be defined using parentheses and `·` as a placeholder.
```lean
#check (. + 1)
-- fun a => a + 1
#check (· + 1)
-- fun a => a + 1
#check (2 - .)
#check (2 - ·)
-- fun a => 2 - a
#eval [1, 2, 3, 4, 5].foldl (. * .) 1
#eval [1, 2, 3, 4, 5].foldl (· * ·) 1
-- 120
def h (x y z : Nat) :=
x + y + z
#check (h . 1 .)
#check (h · 1 ·)
-- fun a b => h a 1 b
#eval [(1, 2), (3, 4), (5, 6)].map (·.1)
-- [1, 3, 5]
```
In the previous example, the term `(·.1)` is syntax sugar for `fun x => x.1`. Note that, the ASCII version `(..1)`
is not supported because `..` is a reserved symbol.
In the previous example, the term `(·.1)` is syntax sugar for `fun x => x.1`.
# Pipelining
@@ -111,14 +127,14 @@ In contrast, the backward pipeline `<|` operator takes an argument and a functio
These operators are useful for minimizing the number of parentheses.
```lean
def add1Times3FilterEven (xs : List Nat) :=
List.filter (. % 2 == 0) (List.map (. * 3) (List.map (. + 1) xs))
List.filter (· % 2 == 0) (List.map (· * 3) (List.map (· + 1) xs))
#eval add1Times3FilterEven [1, 2, 3, 4]
-- [6, 12]
-- Define the same function using pipes
def add1Times3FilterEven' (xs : List Nat) :=
xs |> List.map (. + 1) |> List.map (. * 3) |> List.filter (. % 2 == 0)
xs |> List.map (· + 1) |> List.map (· * 3) |> List.filter (· % 2 == 0)
#eval add1Times3FilterEven' [1, 2, 3, 4]
-- [6, 12]
@@ -127,7 +143,7 @@ Lean also supports the operator `|>.` which combines forward pipeline `|>` opera
```lean
-- Define the same function using pipes
def add1Times3FilterEven'' (xs : List Nat) :=
xs.map (. + 1) |>.map (. * 3) |>.filter (. % 2 == 0)
xs.map (· + 1) |>.map (· * 3) |>.filter (· % 2 == 0)
#eval add1Times3FilterEven'' [1, 2, 3, 4]
-- [6, 12]

View File

@@ -1111,9 +1111,9 @@ hljs.registerLanguage("lean", function(hljs) {
'axiom constant ' +
'partial unsafe private protected ' +
'if then else ' +
'universe variable variables ' +
'import open export theory prelude renaming hiding exposing ' +
'calc match with do by let extends ' +
'universe variable ' +
'import open export prelude renaming hiding ' +
'calc match with do by let extends ' +
'for in unless try catch finally mutual mut return continue break where rec ' +
'syntax macro_rules macro deriving ' +
'fun ' +
@@ -1123,7 +1123,7 @@ hljs.registerLanguage("lean", function(hljs) {
'Type Prop|10 Sort rw|10 rewrite rwa erw subst substs ' +
'simp dsimp simpa simp_intros finish using generalizing ' +
'unfold unfold1 dunfold unfold_projs unfold_coes ' +
'delta cc ac_reflexivity ac_refl ' +
'delta cc ac_rfl ' +
'existsi|10 cases rcases intro intros introv by_cases ' +
'refl rfl funext case focus propext exact exacts ' +
'refine apply eapply fapply apply_with apply_instance ' +

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 28 KiB

BIN
doc/images/install_elan.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

55
doc/images/monads.dgml Normal file
View File

@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8"?>
<DirectedGraph GraphDirection="TopToBottom" Layout="Sugiyama" Offset="-1264.63833333333,-729.52" ZoomLevel="1" xmlns="http://schemas.microsoft.com/vs/2009/dgml">
<Nodes>
<Node Id="Applicative" Bounds="-839,-412,78.3066666666667,25.96" UseManualLocation="True" />
<Node Id="Bind" Bounds="-703,-412.990048779297,50,25.96" UseManualLocation="True" />
<Node Id="Except" Category="concrete" Bounds="-631,-238,54.5166666666667,25.96" UseManualLocation="True" />
<Node Id="Functor" Bounds="-890.021657986111,-509,60.2533333333333,25.96" UseManualLocation="True" />
<Node Id="List" Category="concrete" Bounds="-922,-412,50,25.96" UseManualLocation="True" />
<Node Id="Monad" Bounds="-765,-339,57.77,25.96" UseManualLocation="True" />
<Node Id="Option" Category="concrete" Bounds="-903,-238,56.8933333333333,25.96" UseManualLocation="True" />
<Node Id="Pure" Bounds="-799,-509,50,25.96" UseManualLocation="True" />
<Node Id="ReaderM" Category="concrete" Bounds="-816,-238,67.5033333333333,25.96" UseManualLocation="True" />
<Node Id="Seq" Bounds="-719,-509,50,25.96" UseManualLocation="True" />
<Node Id="SeqLeft" Bounds="-639,-509,59.4666666666667,25.96" UseManualLocation="True" />
<Node Id="SeqRight" Bounds="-544,-509,67.7233333333333,25.96" UseManualLocation="True" />
<Node Id="StateM" Category="concrete" Bounds="-718.358888888889,-238,57.28,25.96" UseManualLocation="True" />
</Nodes>
<Links>
<Link Source="Applicative" Target="Functor" Bounds="-847.12242702921,-475.387638592472,39.2404278471513,63.3876385924717" />
<Link Source="Applicative" Target="Pure" Bounds="-796.388009621993,-474.343439288465,16.6120628262117,62.3434392884653" />
<Link Source="Applicative" Target="Seq" Bounds="-785.682854982818,-476.959367842732,70.8838407724442,64.9593678427323" />
<Link Source="Applicative" Target="SeqLeft" Bounds="-774.344312027491,-478.957606209781,131.554439087217,66.9576062097807" />
<Link Source="Applicative" Target="SeqRight" Bounds="-762.225406557428,-481.91850535998,209.970366938847,70.3021737715571" />
<Link Source="Except" Target="Monad" Bounds="-711.95378637201,-307.579654923495,91.1658051838909,69.5796549234947" />
<Link Source="List" Target="Functor" Bounds="-892.034814302334,-474.634018472681,23.9591319497622,62.6340184726814" />
<Link Source="Monad" Target="Applicative" Bounds="-782.595654197137,-379.260216894652,35.1486400418858,40.2602168946518" />
<Link Source="Monad" Target="Bind" Bounds="-725.919943874952,-379.952252619104,32.1656790368972,40.9522526191042" />
<Link Source="Option" Target="Monad" Bounds="-856.761951485149,-307.735551794831,95.5848867777901,69.7355517948313" />
<Link Source="ReaderM" Target="Monad" Bounds="-776.319514851485,-304.853562563497,30.5364127352738,66.8535625634966" />
<Link Source="StateM" Target="Monad" Bounds="-726.395530552052,-304.861622913356,30.7140523342301,66.8616229133556" />
</Links>
<Categories>
<Category Id="concrete" />
</Categories>
<Properties>
<Property Id="Bounds" DataType="System.Windows.Rect" />
<Property Id="Expression" DataType="System.String" />
<Property Id="GraphDirection" DataType="Microsoft.VisualStudio.Diagrams.Layout.LayoutOrientation" />
<Property Id="GroupLabel" DataType="System.String" />
<Property Id="IsEnabled" DataType="System.Boolean" />
<Property Id="Layout" DataType="System.String" />
<Property Id="Offset" DataType="System.String" />
<Property Id="TargetType" DataType="System.Type" />
<Property Id="UseManualLocation" DataType="System.Boolean" />
<Property Id="Value" DataType="System.String" />
<Property Id="ValueLabel" DataType="System.String" />
<Property Id="ZoomLevel" DataType="System.String" />
</Properties>
<Styles>
<Style TargetType="Node" GroupLabel="concrete" ValueLabel="True">
<Condition Expression="HasCategory('concrete')" />
<Setter Property="Background" Value="#FF91E7ED" />
</Style>
</Styles>
</DirectedGraph>

106
doc/images/monads.svg Normal file
View File

@@ -0,0 +1,106 @@
<?xml version="1.0" encoding="utf-8"?>
<svg stroke-linecap="round" font-size="12" font-family="Segoe UI" width="485.7233333333333" height="336.96000000000004" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg">
<defs />
<g transform="translate(942,529)">
<g id="Applicative-&gt;Functor">
<path d="M -807.881999182059,-412 L -847.12242702921,-475.387638592472" fill="none" stroke="#A0A0A0" stroke-width="1" />
<path d="M -851.859658804052,-483.04 L -849.997117457574,-472.431939869483 C -848.256110200696,-474.68582647768 -845.988743857725,-476.089450707263 -843.19501842866,-476.642812558231 z" fill="#A0A0A0" stroke="#A0A0A0" stroke-width="1" stroke-linejoin="round" />
</g>
<g id="Applicative-&gt;Pure">
<path d="M -796.388009621993,-412 L -779.775946795781,-474.343439288465" fill="none" stroke="#A0A0A0" stroke-width="1" />
<path d="M -777.458657044673,-483.04 L -783.898561528809,-474.407061321009 C -781.064326160453,-474.686741473815 -778.487567431109,-474.000137103116 -776.168285340778,-472.347248208913 z" fill="#A0A0A0" stroke="#A0A0A0" stroke-width="1" stroke-linejoin="round" />
</g>
<g id="Applicative-&gt;Seq">
<path d="M -785.682854982818,-412 L -714.799014210374,-476.959367842732" fill="none" stroke="#A0A0A0" stroke-width="1" />
<path d="M -708.163811683849,-483.04 L -718.238762116551,-479.232720948158 C -715.699848604043,-477.942360809625 -713.898179816704,-475.97637487584 -712.833755754535,-473.334763146803 z" fill="#A0A0A0" stroke="#A0A0A0" stroke-width="1" stroke-linejoin="round" />
</g>
<g id="Applicative-&gt;SeqLeft">
<path d="M -774.344312027491,-412 L -642.789872940275,-478.957606209781" fill="none" stroke="#A0A0A0" stroke-width="1" />
<path d="M -634.769021305842,-483.04 L -645.495475917531,-482.068829848393 C -643.394672020307,-480.145880525993 -642.185073860242,-477.769331893569 -641.866681437336,-474.93918395112 z" fill="#A0A0A0" stroke="#A0A0A0" stroke-width="1" stroke-linejoin="round" />
</g>
<g id="Applicative-&gt;SeqRight">
<path d="M -762.225406557428,-411.616331588423 L -552.255039618581,-481.91850535998" fill="none" stroke="#A0A0A0" stroke-width="1" />
<path d="M -543.720702607113,-484.775967831244 L -554.473282607084,-485.394048201604 C -552.678367392102,-483.182851583901 -551.831711845061,-480.654159136059 -551.93331596596,-477.807970858076 z" fill="#A0A0A0" stroke="#A0A0A0" stroke-width="1" stroke-linejoin="round" />
</g>
<g id="Except-&gt;Monad">
<path d="M -620.787981188119,-238 L -711.95378637201,-307.579654923495" fill="none" stroke="#A0A0A0" stroke-width="1" />
<path d="M -719.108129922992,-313.04 L -713.585679344792,-303.793241670113 C -712.762726383344,-306.519752175201 -711.144846360676,-308.639557671788 -708.732039276787,-310.152658159875 z" fill="#A0A0A0" stroke="#A0A0A0" stroke-width="1" stroke-linejoin="round" />
</g>
<g id="List-&gt;Functor">
<path d="M -892.034814302334,-412 L -868.075682352572,-474.634018472681" fill="none" stroke="#A0A0A0" stroke-width="1" />
<path d="M -864.86017701711,-483.04 L -872.168952513098,-475.129134007629 C -869.321012949211,-475.110389633491 -866.830351755932,-474.157647311872 -864.696968933259,-472.270907042774 z" fill="#A0A0A0" stroke="#A0A0A0" stroke-width="1" stroke-linejoin="round" />
</g>
<g id="Monad-&gt;Applicative">
<path d="M -747.447014155251,-339 L -782.595654197137,-379.260216894652" fill="none" stroke="#A0A0A0" stroke-width="1" />
<path d="M -788.514652511416,-386.04 L -784.951224653483,-375.876241743267 C -783.60006650904,-378.383328255499 -781.591241885233,-380.137105533804 -778.924750782062,-381.137573578181 z" fill="#A0A0A0" stroke="#A0A0A0" stroke-width="1" stroke-linejoin="round" />
</g>
<g id="Monad-&gt;Bind">
<path d="M -725.919943874952,-339 L -693.754264838054,-379.952252619104" fill="none" stroke="#A0A0A0" stroke-width="1" />
<path d="M -688.195056125048,-387.030048779297 L -697.517641877363,-381.63659025153 C -694.802827232157,-380.775839095105 -692.705702443952,-379.128666143103 -691.226267512747,-376.695071395525 z" fill="#A0A0A0" stroke="#A0A0A0" stroke-width="1" stroke-linejoin="round" />
</g>
<g id="Option-&gt;Monad">
<path d="M -856.761951485149,-238 L -761.177064707358,-307.735551794831" fill="none" stroke="#A0A0A0" stroke-width="1" />
<path d="M -753.906381848185,-313.04 L -764.342450894008,-310.377583265001 C -761.962908885902,-308.81268999619 -760.391220528815,-306.658413593472 -759.627385822747,-303.914754056846 z" fill="#A0A0A0" stroke="#A0A0A0" stroke-width="1" stroke-linejoin="round" />
</g>
<g id="ReaderM-&gt;Monad">
<path d="M -776.319514851485,-238 L -745.783102116211,-304.853562563497" fill="none" stroke="#A0A0A0" stroke-width="1" />
<path d="M -742.043818481848,-313.04 L -749.836994714031,-305.60586224138 C -746.99590766236,-305.407530509328 -744.570296570063,-304.299594617665 -742.560161437139,-302.28205456639 z" fill="#A0A0A0" stroke="#A0A0A0" stroke-width="1" stroke-linejoin="round" />
</g>
<g id="StateM-&gt;Monad">
<path d="M -695.681478217822,-238 L -726.395530552052,-304.861622913356" fill="none" stroke="#A0A0A0" stroke-width="1" />
<path d="M -730.152410671067,-313.04 L -729.612933688448,-302.283189850833 C -727.607141972296,-304.305048080909 -725.183919131808,-305.418197745802 -722.343265166986,-305.622638845513 z" fill="#A0A0A0" stroke="#A0A0A0" stroke-width="1" stroke-linejoin="round" />
</g>
<g id="Applicative">
<rect x="-839" y="-412" rx="3" ry="3" width="78.3066666666667" height="25.96" fill="#FFFFFF" stroke="#A5A6A9" stroke-width="1" />
<text x="-829" y="-394.05" fill="#3D3D3D">Applicative</text>
</g>
<g id="Bind">
<rect x="-703" y="-412.990048779297" rx="3" ry="3" width="50" height="25.96" fill="#FFFFFF" stroke="#A5A6A9" stroke-width="1" />
<text x="-690" y="-395.040048779297" fill="#3D3D3D">Bind</text>
</g>
<g id="Except">
<rect x="-631" y="-238" rx="3" ry="3" width="54.5166666666667" height="25.96" fill="#91E7ED" stroke="#A5A6A9" stroke-width="1" />
<text x="-621" y="-220.05" fill="#3D3D3D">Except</text>
</g>
<g id="Functor">
<rect x="-890.021657986111" y="-509" rx="3" ry="3" width="60.2533333333333" height="25.96" fill="#FFFFFF" stroke="#A5A6A9" stroke-width="1" />
<text x="-880.021657986111" y="-491.05" fill="#3D3D3D">Functor</text>
</g>
<g id="List">
<rect x="-922" y="-412" rx="3" ry="3" width="50" height="25.96" fill="#91E7ED" stroke="#A5A6A9" stroke-width="1" />
<text x="-906" y="-394.05" fill="#3D3D3D">List</text>
</g>
<g id="Monad">
<rect x="-765" y="-339" rx="3" ry="3" width="57.77" height="25.96" fill="#FFFFFF" stroke="#A5A6A9" stroke-width="1" />
<text x="-755" y="-321.05" fill="#3D3D3D">Monad</text>
</g>
<g id="Option">
<rect x="-903" y="-238" rx="3" ry="3" width="56.8933333333333" height="25.96" fill="#91E7ED" stroke="#A5A6A9" stroke-width="1" />
<text x="-893" y="-220.05" fill="#3D3D3D">Option</text>
</g>
<g id="Pure">
<rect x="-799" y="-509" rx="3" ry="3" width="50" height="25.96" fill="#FFFFFF" stroke="#A5A6A9" stroke-width="1" />
<text x="-786" y="-491.05" fill="#3D3D3D">Pure</text>
</g>
<g id="ReaderM">
<rect x="-816" y="-238" rx="3" ry="3" width="67.5033333333333" height="25.96" fill="#91E7ED" stroke="#A5A6A9" stroke-width="1" />
<text x="-806" y="-220.05" fill="#3D3D3D">ReaderM</text>
</g>
<g id="Seq">
<rect x="-719" y="-509" rx="3" ry="3" width="50" height="25.96" fill="#FFFFFF" stroke="#A5A6A9" stroke-width="1" />
<text x="-704" y="-491.05" fill="#3D3D3D">Seq</text>
</g>
<g id="SeqLeft">
<rect x="-639" y="-509" rx="3" ry="3" width="59.4666666666667" height="25.96" fill="#FFFFFF" stroke="#A5A6A9" stroke-width="1" />
<text x="-629" y="-491.05" fill="#3D3D3D">SeqLeft</text>
</g>
<g id="SeqRight">
<rect x="-544" y="-509" rx="3" ry="3" width="67.7233333333333" height="25.96" fill="#FFFFFF" stroke="#A5A6A9" stroke-width="1" />
<text x="-534" y="-491.05" fill="#3D3D3D">SeqRight</text>
</g>
<g id="StateM">
<rect x="-718.358888888889" y="-238" rx="3" ry="3" width="57.28" height="25.96" fill="#91E7ED" stroke="#A5A6A9" stroke-width="1" />
<text x="-708.358888888889" y="-220.05" fill="#3D3D3D">StateM</text>
</g>
</g>
</svg>

BIN
doc/images/widgets_caas.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

View File

@@ -64,7 +64,7 @@ It makes these three arguments implicit. Notationally, this hides the specificat
making it look as though ``compose`` simply takes 3 arguments.
Variables can also be specified as implicit when they are declared with
the ``variables`` command:
the ``variable`` command:
```lean
universe u

View File

@@ -1,3 +1,3 @@
# Inductive Types
TODO
[Theorem Proving in Lean](https://leanprover.github.io/theorem_proving_in_lean4/inductive_types.html) has a chapter about inductive datatypes.

View File

@@ -33,14 +33,13 @@ class Lean4Lexer(RegexLexer):
keywords1 = (
'import', 'abbreviation', 'opaque_hint', 'tactic_hint', 'definition',
'renaming', 'inline', 'hiding', 'exposing', 'parameter', 'parameters',
'conjecture', 'hypothesis', 'lemma', 'corollary', 'variable', 'variables',
'renaming', 'inline', 'hiding', 'parameter', 'lemma', 'variable',
'theorem', 'axiom', 'inductive', 'structure', 'universe', 'alias',
'help', 'options', 'precedence', 'postfix', 'prefix', 'calc_trans',
'calc_subst', 'calc_refl', 'infix', 'infixl', 'infixr', 'notation', '#eval',
'help', 'options', 'precedence', 'postfix', 'prefix',
'infix', 'infixl', 'infixr', 'notation', '#eval',
'#check', '#reduce', '#exit', 'coercion', 'end', 'private', 'using', 'namespace',
'including', 'instance', 'section', 'context', 'protected', 'expose',
'export', 'set_option', 'add_rewrite', 'extends', 'open', 'example',
'export', 'set_option', 'extends', 'open', 'example',
'constant', 'constants', 'print', 'opaque', 'reducible', 'irreducible',
'def', 'macro', 'elab', 'syntax', 'macro_rules', 'reduce', 'where',
'abbrev', 'noncomputable', 'class', 'attribute', 'synth', 'mutual',

View File

@@ -12,21 +12,22 @@ texcl=false,
% keywords, list taken from lean-syntax.el
morekeywords=[1]{
import, prelude, protected, private, noncomputable, definition, meta, renaming,
hiding, exposing, parameter, parameters, begin, conjecture, constant, constants,
hypothesis, lemma, corollary, variable, variables, premise, premises, theory,
print, theorem, proposition, example,
open, as, export, override, axiom, axioms, inductive, with, without,
hiding, parameter, parameters, begin, constant, constants,
lemma, variable, variables, theory,
print, theorem, example,
open, as, export, override, axiom, axioms, inductive, with,
structure, record, universe, universes,
alias, help, precedence, reserve, declare_trace, add_key_equivalence,
match, infix, infixl, infixr, notation, postfix, prefix, instance,
eval, vm_eval, check, coercion, end, this, suppose,
using, using_well_founded, namespace, section, fields,
attribute, local, set_option, extends, include, omit, classes, class,
instances, coercions, attributes, raw, replacing,
eval, reduce, check, end, this,
using, using_well_founded, namespace, section,
attribute, local, set_option, extends, include, omit, class,
raw, replacing,
calc, have, show, suffices, by, in, at, let, forall, Pi, fun,
exists, if, dif, then, else, assume, obtain, from, aliases, register_simp_ext, unless, break, continue,
mutual, do, def, run_cmd, const
partial,mut,where,macro,syntax,deriving, return, try, catch, for, macro_rules,declare_syntax_cat,abbrev},
exists, if, dif, then, else, assume, obtain, from, register_simp_ext, unless, break, continue,
mutual, do, def, run_cmd, const,
partial, mut, where, macro, syntax, deriving,
return, try, catch, for, macro_rules, declare_syntax_cat, abbrev},
% Sorts
morekeywords=[2]{Sort, Type, Prop},

View File

@@ -14,7 +14,7 @@ to separate the elements of a list, and in the lambda expression itself. We now
as an example, `fun x => x` is the identity function. One may still use the symbol `λ` as a shorthand for `fun`.
The lambda expression notation has many new features that are not supported in Lean 3.
* Pattern matching
## Pattern matching
In Lean 4, one can easily create new notation that abbreviates commonly used idioms. One of them is a
`fun` followed by a `match`. In the following examples, we define a few functions using `fun`+`match` notation.
@@ -39,7 +39,7 @@ def Sum.str : Option Nat → String :=
# end ex1
```
* Implicit lambdas
## Implicit lambdas
In Lean 3 stdlib, we find many [instances](https://github.com/leanprover/lean/blob/master/library/init/category/reader.lean#L39) of the dreadful `@`+`_` idiom.
It is often used when we the expected type is a function type with implicit arguments,
@@ -83,7 +83,7 @@ def id5 : {α : Type} → αα :=
# end ex2
```
* Sugar for simple functions
## Sugar for simple functions
In Lean 3, we can create simple functions from infix operators by using parentheses. For example, `(+1)` is sugar for `fun x, x + 1`. In Lean 4, we generalize this notation using `·` As a placeholder. Here are a few examples:
@@ -230,11 +230,10 @@ restriction imposed by ordinary type theory. Metadefinitions may also use unsafe
The keyword `meta` has been currently removed from Lean 4. However, we may re-introduce it in the future,
but with a much more limited purpose: marking meta code that should not be included in the executables produced by Lean.
The keywords `axiom` and `constant` are not equivalent in Lean 4. In Lean 4, `constant` is used to define
an opaque definition. Here are two simple examples:
The keyword `constant` has been deleted in Lean 4, and `axiom` should be used instead. In Lean 4, the new command `opaque` is used to define an opaque definition. Here are two simple examples:
```lean
# namespace meta1
constant x : Nat := 1
opaque x : Nat := 1
-- The following example will not type check since `x` is opaque
-- example : x = 1 := rfl
@@ -244,11 +243,11 @@ constant x : Nat := 1
-- When no value is provided, the elaborator tries to build one automatically for us
-- using the `Inhabited` type class
constant y : Nat
opaque y : Nat
# end meta1
```
We can instruct Lean to use a foreign function as the implementation for any constant or definition
We can instruct Lean to use a foreign function as the implementation for any definition
using the attribute `@[extern "foreign_function"]`. It is the user's responsibility to ensure the
foreign implementation is correct.
However, a user mistake here will only impact the code generated by Lean, and
@@ -336,3 +335,34 @@ partial def f (x : Nat) : IO Unit := do
#eval f 98
# end partial1
```
## Library changes
These are changes to the library which may trip up Lean 3 users:
- `Option` and `List` are no longer monads. Instead there is `OptionM`. This was done to avoid some performance traps. For example `o₁ <|> o₂` where `o₁ o₂ : Option α` will evaluate both `o₁` and `o₂` even if `o₁` evaluates to `some x`. This can be a problem if `o₂` requires a lot of compute to evaluate. A zulip discussion on this design choice is [here](https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/Option.20do.20notation.20regression.3F).
## Style changes
Coding style changes have also been made:
- Term constants and variables are now `lowerCamelCase` rather than `snake_case`
- Type constants are now `UpperCamelCase`, eg `Nat`, `List`. Type variables are still lower case greek letters. Functors are still lower case latin `(m : Type → Type) [Monad m]`.
- When defining typeclasses, prefer not to use "has". Eg `ToString` or `Add` instead of `HasToString` or `HasAdd`.
- Prefer `return` to `pure` in monad expressions.
- Pipes `<|` are preferred to dollars `$` for function application.
- Declaration bodies should always be indented:
```lean
inductive Hello where
| foo
| bar
structure Point where
x : Nat
y : Nat
def Point.addX : Point → Point → Nat :=
fun { x := a, .. } { x := b, .. } => a + b
```
- In structures and typeclass definitions, prefer `where` to `:=` and don't surround fields with parentheses. (Shown in `Point` above)

View File

@@ -158,7 +158,7 @@ Output:
[Elab.definition.body] binderterm.quot : Lean.ParserDescr :=
Lean.ParserDescr.node `Lean.Parser.Term.quot 1024
(Lean.ParserDescr.binary `andthen (Lean.ParserDescr.symbol "`(binderterm|")
(Lean.ParserDescr.binary `andthen (Lean.ParserDescr.unary `incQuotDepth (Lean.ParserDescr.cat `binderterm 0))
(Lean.ParserDescr.binary `andthen (Lean.ParserDescr.cat `binderterm 0)
(Lean.ParserDescr.symbol ")")))
-/
```

View File

@@ -46,9 +46,8 @@ For example, on an AMD Ryzen 9 `make` takes 00:04:55, whereas `make -j 10`
takes 00:01:38. Your results may vary depending on the speed of your hard
drive.
To install the build, see [Dev setup using
elan](../dev/index.md#dev-setup-using-elan).
You should not usually run `make install` after a successful build.
See [Dev setup using elan](../dev/index.md#dev-setup-using-elan) on how to properly set up your editor to use the correct stage depending on the source directory.
Useful CMake Configuration Settings
-----------------------------------

View File

@@ -18,8 +18,7 @@ the stdlib.
## Installing dependencies
[The official webpage of MSYS2][msys2] provides one-click installers.
Once installed, you should run the "MSYS2 MinGW 64-bit shell" from the start menu.
(The one that runs `mingw64.exe`)
Once installed, you should run the "MSYS2 MinGW 64-bit shell" from the start menu (the one that runs `mingw64.exe`).
Do not run "MSYS2 MSYS" instead!
MSYS2 has a package management system, [pacman][pacman], which is used in Arch Linux.
@@ -74,6 +73,11 @@ The following linux command will do that:
cp $(ldd lean.exe | cut -f3 -d' ' | grep mingw) .
```
However, if you plan to use this build to compile lean programs
to executable binaries using `lake build` in normal Windows command
prompt outside of msys2 environment you will also need to add a windows
version clang to your path.
## Trouble shooting
**-bash: gcc: command not found**

View File

@@ -10,7 +10,7 @@ Follow the setup in the link above; to open the Lean shell inside a Lean checkou
$ nix-shell -A nix
```
On top of the local and remote Nix cache, it helps to we do still rely on CCache as well to make C/C++ build steps incremental, which are atomic steps from Nix's point of view.
On top of the local and remote Nix cache, we do still rely on CCache as well to make C/C++ build steps incremental, which are atomic steps from Nix's point of view.
To enable CCache, add the following line to the config file mentioned in the setup:
```bash
extra-sandbox-paths = /nix/var/cache/ccache
@@ -35,7 +35,7 @@ The `stage1.` part in each command is optional:
```bash
nix build .#test # run tests for stage 1
nix build . # build stage 1
nix build # dito
nix build # ditto
```
## Build Process Description
@@ -52,11 +52,14 @@ This is because modules are discovered not from a directory listing anymore but
As in the standard Nix setup.
After adding `src/` as an LSP workspace, it should automatically fall back to using stage 0 in there.
Note that the UX of `emacs/vscode-dev` is quite different from the Make-based setup regarding the compilation of dependencies:
Note that the UX of `{emacs,vscode}-dev` is quite different from the Make-based setup regarding the compilation of dependencies:
there is no mutable directory incrementally filled by the build that we could point the editor at for .olean files.
Instead, `emacs-dev` will gather the individual dependency outputs from the Nix store when checking a file -- and build them on the fly when necessary.
However, it will only ever load changes saved to disk, not ones opened in other buffers.
The absence of a mutable output directory also means that the Lean server will not automatically pick up `.ilean` metadata from newly compiled files.
Instead, you can run `nix run .#link-ilean` to symlink the `.ilean` tree of the stdlib state at that point in time to `src/build/lib`, where the server should automatically find them.
## Other Fun Stuff to Do with Nix
Open Emacs with Lean set up from an arbitrary commit (without even cloning Lean beforehand... if your Nix is new enough):
@@ -86,7 +89,7 @@ nix run .#HEAD-as-stage0.emacs-dev&
```
To run `nix build` on the second stage outside of the second editor, use
```bash
nix build .#stage0-from-input
nix build .#stage0-from-input --override-input lean-stage0 .\?rev=$(git rev-parse HEAD)
```
This setup will inadvertently change your `flake.lock` file, which you can revert when you are done.

View File

@@ -0,0 +1,58 @@
inductive Arith : Type
| add : Arith Arith Arith -- e + f
| mul : Arith Arith Arith -- e * f
| int : Int Arith -- constant
| symbol : String Arith -- variable
declare_syntax_cat arith
syntax num : arith -- int for Arith.int
syntax str : arith -- strings for Arith.symbol
syntax:60 arith:60 "+" arith:61 : arith -- Arith.add
syntax:70 arith:70 "*" arith:71 : arith -- Arith.mul
syntax "(" arith ")" : arith -- parenthesized expressions
-- auxiliary notation for translating `arith` into `term`
syntax "`[Arith| " arith "]" : term
macro_rules
| `(`[Arith| $s:str]) => `(Arith.symbol $s)
| `(`[Arith| $num:num]) => `(Arith.int $num)
| `(`[Arith| $x + $y]) => `(Arith.add `[Arith| $x] `[Arith| $y])
| `(`[Arith| $x * $y]) => `(Arith.mul `[Arith| $x] `[Arith| $y])
| `(`[Arith| ($x)]) => `(`[Arith| $x])
#check `[Arith| "x" * "y"] -- mul
-- Arith.mul (Arith.symbol "x") (Arith.symbol "y")
#check `[Arith| "x" + "y"] -- add
-- Arith.add (Arith.symbol "x") (Arith.symbol "y")
#check `[Arith| "x" + 20] -- symbol + int
-- Arith.add (Arith.symbol "x") (Arith.int 20)
#check `[Arith| "x" + "y" * "z"] -- precedence
-- Arith.add (Arith.symbol "x") (Arith.mul (Arith.symbol "y") (Arith.symbol "z"))
#check `[Arith| "x" * "y" + "z"] -- precedence
-- Arith.add (Arith.mul (Arith.symbol "x") (Arith.symbol "y")) (Arith.symbol "z")
#check `[Arith| ("x" + "y") * "z"] -- parentheses
-- Arith.mul (Arith.add (Arith.symbol "x") (Arith.symbol "y")) (Arith.symbol "z")
syntax ident : arith
macro_rules
| `(`[Arith| $x:ident]) => `(Arith.symbol $(Lean.quote (toString x.getId)))
#check `[Arith| x] -- Arith.symbol "x"
def xPlusY := `[Arith| x + y]
#print xPlusY -- def xPlusY : Arith := Arith.add (Arith.symbol "x") (Arith.symbol "y")
syntax "<[" term "]>" : arith -- escape for embedding terms into `Arith`
macro_rules
| `(`[Arith| <[ $e:term ]>]) => pure e
#check `[Arith| <[ xPlusY ]> + z] -- Arith.add xPlusY (Arith.symbol "z")

View File

@@ -0,0 +1,134 @@
# Arithmetic as an embedded domain-specific language
Let's parse another classic grammar, the grammar of arithmetic expressions with
addition, multiplication, integers, and variables. In the process, we'll learn
how to:
- Convert identifiers such as `x` into strings within a macro.
- add the ability to "escape" the macro context from within the macro. This is useful to interpret identifiers with their _original_ meaning (predefined values)
instead of their new meaning within a macro (treat as a symbol).
Let's begin with the simplest thing possible. We'll define an AST, and use operators `+` and `*` to denote
building an arithmetic AST.
Here's the AST that we will be parsing:
```lean,ignore
{{#include metaprogramming-arith.lean:1:5}}
```
We declare a syntax category to describe the grammar that we will be parsing.
See that we control the precedence of `+` and `*` by writing `syntax:50` for addition and `syntax:60` for multiplication,
indicating that multiplication binds tighter than addition (higher the number, tighter the binding).
This allows us to declare _precedence_ when defining new syntax.
```lean,ignore
{{#include metaprogramming-arith.lean:7:13}}
```
Further, if we look at `syntax:60 arith:60 "+" arith:61 : arith`, the
precedence declarations at `arith:60 "+" arith:61` conveys that the left
argument must have precedence at least `60` or greater, and the right argument
must have precedence at least`61` or greater. Note that this forces left
associativity. To understand this, let's compare two hypothetical parses:
```
-- syntax:60 arith:60 "+" arith:61 : arith -- Arith.add
-- a + b + c
(a:60 + b:61):60 + c
a + (b:60 + c:61):60
```
In the parse tree of `a + (b:60 + c:61):60`, we see that the right argument `(b + c)` is given the precedence `60`. However,
the rule for addition expects the right argument to have a precedence of **at least** 61, as witnessed by the `arith:61` at
the right-hand-side of `syntax:60 arith:60 "+" arith:61 : arith`. Thus, the rule `syntax:60 arith:60 "+" arith:61 : arith`
ensures that addition is left associative.
Since addition is declared arguments of precedence `60/61` and multiplication with `70/71`, this causes multiplication to bind
tighter than addition. Once again, let's compare two hypothetical parses:
```
-- syntax:60 arith:60 "+" arith:61 : arith -- Arith.add
-- syntax:70 arith:70 "*" arith:71 : arith -- Arith.mul
-- a * b + c
a * (b:60 + c:61):60
(a:70 * b:71):70 + c
```
While parsing `a * (b + c)`, `(b + c)` is assigned a precedence `60` by the addition rule. However, multiplication expects
the right argument to have precedence **at least** 71. Thus, this parse is invalid. In contrast, `(a * b) + c` assigns
a precedence of `70` to `(a * b)`. This is compatible with addition which expects the left argument to have precedence
**at least `60` ** (`70` is greater than `60`). Thus, the string `a * b + c` is parsed as `(a * b) + c`.
For more details, please look at the [Lean manual on syntax extensions](../syntax.md#notations-and-precedence).
To go from strings into `Arith`, we define a macro to
translate the syntax category `arith` into an `Arith` inductive value that
lives in `term`:
```lean,ignore
{{#include metaprogramming-arith.lean:15:16}}
```
Our macro rules perform the "obvious" translation:
```lean,ignore
{{#include metaprogramming-arith.lean:18:23}}
```
And some examples:
```lean,ignore
{{#include metaprogramming-arith.lean:25:41}}
```
Writing variables as strings, such as `"x"` gets old; wouldn't it be so much
prettier if we could write `x * y`, and have the macro translate this into `Arith.mul (Arith.Symbol "x") (Arith.mul "y")`?
We can do this, and this will be our first taste of manipulating macro variables --- we'll use `x.getId` instead of directly evaluating `$x`.
We also write a macro rule for `Arith|` that translates an identifier into
a string, using `$(Lean.quote (toString x.getId))`:
```lean,ignore
{{#include metaprogramming-arith.lean:43:46}}
```
Let's test and see that we can now write expressions such as `x * y` directly instead of having to write `"x" * "y"`:
```lean,ignore
{{#include metaprogramming-arith.lean:48:51}}
```
We now show an unfortunate consequence of the above definitions. Suppose we want to build `(x + y) + z`.
Since we already have defined `xPlusY` as `x + y`, perhaps we should reuse it! Let's try:
```lean,ignore
#check `[Arith| xPlusY + z] -- Arith.add (Arith.symbol "xPlusY") (Arith.symbol "z")
```
Whoops, that didn't work! What happened? Lean treats `xPlusY` _itself_ as an identifier! So we need to add some syntax
to be able to "escape" the `Arith|` context. Let's use the syntax `<[ $e:term ]>` to mean: evaluate `$e` as a real term,
not an identifier. The macro looks like follows:
```lean,ignore
{{#include metaprogramming-arith.lean:53:56}}
```
Let's try our previous example:
```lean,ignore
{{#include metaprogramming-arith.lean:58:58}}
```
Perfect!
In this tutorial, we expanded on the previous tutorial to parse a more
realistic grammar with multiple levels of precedence, how to parse identifiers directly
within a macro, and how to provide an escape from within the macro context.
#### Full code listing
```lean
{{#include metaprogramming-arith.lean}}
```

View File

@@ -1,10 +0,0 @@
# Metaprogramming
Macros are a language feature that allows writing code that writes other code (metaprogramming).
In Lean 4, macros are used pervasively. So much so that core language features such as `do` notation
is implemented via macros! As a language user, macros are useful to easily
embed domain-specific languages and to generate code at compile-time, to name a few uses.
## References
- [Hygenic Macro Expansion for Theorem Proving Languages](https://arxiv.org/abs/2001.10490)

1
doc/monads/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
*.lean.md

View File

@@ -0,0 +1,326 @@
/-!
# Applicative Functors
Building on [Functors](functors.lean.md) is the [Applicative
Functor](https://en.wikipedia.org/wiki/Applicative_functor). For simplicity, you can refer to these
simply as "Applicatives". These are a little tricker than functors, but still simpler than monads.
Let's see how they work!
## What is an Applicative Functor?
An applicative functor is an defines a default or "base" construction for an object and allows
function application to be chained across multiple instances of the structure. All applicative
functors are functors, meaning they must also support the "map" operation.
## How are Applicatives represented in Lean?
An [applicative functor](https://en.wikipedia.org/wiki/Applicative_functor) is an intermediate
structure between `Functor` and `Monad`. It mainly consists of two operations:
* `pure : α → F α`
* `seq : F (α → β) → F α → F β` (written as `<*>`)
The `pure` operator specifies how you can wrap a normal object `α` into an instance of this structure `F α`.
This is the "default" mechanism mentioned above.
The `seq` operator allows you to chain operations by wrapping a function in a structure. The name
"applicative" comes from the fact that you "apply" functions from within the structure, rather than
simply from outside the structure, as was the case with `Functor.map`.
Applicative in Lean is built on some helper type classes, `Functor`, `Pure` and `Seq`:
```lean,ignore
class Applicative (f : Type u → Type v) extends Functor f, Pure f, Seq f, SeqLeft f, SeqRight f where
```
Notice that as with `Functor` it is also a type transformer `(f : Type u → Type v)` and notice the
`extends Functor f` is ensuring the base Functor also performs that same type transformation.
As stated above, all applicatives are then functors. This means you can assume that `map` already
exists for all these types.
The `Pure` base type class is a very simple type class that supplies the `pure` function.
```lean,ignore
class Pure (f : Type u → Type v) where
pure {α : Type u} : α → f α
```
You can think of it as lifing the result of a pure value to some monadic type. The simplest example
of `pure` is the `Option` type:
-/
#eval (pure 10 : Option Nat) -- some 10
/-!
Here we used the `Option` implementation of `pure` to wrap the `Nat 10` value in an `Option Nat`
type resulting in the value `some 10`, and in fact if you look at the Monad instance of `Option` , you
will see that `pure` is indeed implemented using `Option.some`:
-/
instance : Monad Option where
pure := Option.some
/-!
The `Seq` type class is also a simple type class that provides the `seq` operator which can
also be written using the special syntax `<*>`.
```lean,ignore
class Seq (f : Type u → Type v) : Type (max (u+1) v) where
seq : {α β : Type u} → f (α → β) → (Unit → f α) → f β
```
## Basic Applicative Examples
Many of the basic functors also have instances of `Applicative`.
For example, `Option` is also `Applicative`.
So let's take a look and what the `seq` operator can do. Suppose you want to multiply two `Option Nat`
objects. Your first attempt might be this:
-/
#check_failure (some 4) * (some 5) -- failed to synthesize instance
/-!
You then might wonder how to use the `Functor.map` to solve this since you could do these before:
-/
#eval (some 4).map (fun x => x * 5) -- some 20
#eval (some 4).map (· * 5) -- some 20
#eval (· * 5) <$> (some 4) -- some 20
/-!
Remember that `<$>` is the infix notation for `Functor.map`.
The functor `map` operation can apply a multiplication to the value in the `Option` and then lift the
result back up to become a new `Option` , but this isn't what you need here.
The `Seq.seq` operator `<*>` can help since it can apply a function to the items inside a
container and then lift the result back up to the desired type, namely `Option` .
There are two ways to do this:
-/
#eval pure (.*.) <*> some 4 <*> some 5 -- some 20
#eval (.*.) <$> some 4 <*> some 5 -- some 20
/-!
In the first way, we start off by wrapping the function in an applicative using pure. Then we apply
this to the first `Option` , and again to the second `Option` in a chain of operations. So you can see
how `Seq.seq` can be chained in fact, `Seq.seq` is really all about chaining of operations.
But in this case there is a simpler way. In the second way, you can see that "applying" a single
function to a container is the same as using `Functor.map`. So you use `<$>` to "transform" the first
option into an `Option` containing a function, and then apply this function over the second value.
Now if either side is `none`, the result is `none`, as expected, and in this case the
`seq` operator was able to eliminate the multiplication:
-/
#eval (.*.) <$> none <*> some 5 -- none
#eval (.*.) <$> some 4 <*> none -- none
/-!
For a more interesting example, let's make `List` an applicative by adding the following
definition:
-/
instance : Applicative List where
pure := List.pure
seq f x := List.bind f fun y => Functor.map y (x ())
/-!
Notice you can now sequence a _list_ of functions and a _list_ of items.
The trivial case of sequencing a singleton list is in fact the same as `map`, as you saw
earlier with the `Option` examples:
-/
#eval [ (·+2)] <*> [4, 6] -- [6, 8]
#eval (·+2) <$> [4,6] -- [6, 8]
/-!
But now with list it is easier to show the difference when you do this:
-/
#eval [(·+2), (· *3)] <*> [4, 6] -- [6, 8, 12, 18]
/-!
Why did this produce 4 values? The reason is because `<*>` applies _every_ function to _every_
value in a pairwise manner. This makes sequence really convenient for solving certain problems. For
example, how do you get the pairwise combinations of all values from two lists?
-/
#eval Prod.mk <$> [1, 2, 3] <*> [4, 5, 6]
-- [(1, 4), (1, 5), (1, 6), (2, 4), (2, 5), (2, 6), (3, 4), (3, 5), (3, 6)]
/-!
How do you get the sum of these pairwise values?
-/
#eval (·+·) <$> [1, 2, 3] <*> [4, 5, 6]
-- [5, 6, 7, 6, 7, 8, 7, 8, 9]
/-!
Here you can use `<$>` to "transform" each element of the first list into a function, and then apply
these functions over the second list.
If you have 3 lists, and want to find all combinations of 3 values across those lists you
would need helper function that can create a tuple out of 3 values, and Lean provides a
very convenient syntax for that `(·,·,·)`:
-/
#eval (·,·,·) <$> [1, 2] <*> [3, 4] <*> [5, 6]
-- [(1, 3, 5), (1, 3, 6), (1, 4, 5), (1, 4, 6), (2, 3, 5), (2, 3, 6), (2, 4, 5), (2, 4, 6)]
/-!
And you could sum these combinations if you first define a sum function that takes three inputs and
then you could chain apply this over the three lists. Again lean can create such a function
with the expression `(·+·+·)`:
-/
#eval (·+·+·) <$> [1, 2] <*> [3, 4] <*> [5, 6]
-- [9, 10, 10, 11, 10, 11, 11, 12]
/-!
And indeed each sum here matches the expected values if you manually sum the triples we
show above.
**Side note:** there is another way to combine lists with a function that does not do the pairwise
combinatorics, it is called `List.zipWith`:
-/
#eval List.zipWith (·+·) [1, 2, 3] [4, 5, 6]
-- [5, 7, 9]
/-!
And there is a helper function named `List.zip` that calls `zipWith` using the function `Prod.mk`
so you get a nice zipped list like this:
-/
#eval List.zip [1, 2, 3] [4, 5, 6]
-- [(1, 4), (2, 5), (3, 6)]
/-!
And of couse, as you would expect, there is an `unzip` also:
-/
#eval List.unzip (List.zip [1, 2, 3] [4, 5, 6])
-- ([1, 2, 3], [4, 5, 6])
/-!
## Example: A Functor that is not Applicative
From the chapter on [functors](functors.lean.md) you might remember this example of `LivingSpace`
that had a `Functor` instance:
-/
structure LivingSpace (α : Type) where
totalSize : α
numBedrooms : Nat
masterBedroomSize : α
livingRoomSize : α
kitchenSize : α
deriving Repr, BEq
def LivingSpace.map (f : α β) (s : LivingSpace α) : LivingSpace β :=
{ totalSize := f s.totalSize
numBedrooms := s.numBedrooms
masterBedroomSize := f s.masterBedroomSize
livingRoomSize := f s.livingRoomSize
kitchenSize := f s.kitchenSize }
instance : Functor LivingSpace where
map := LivingSpace.map
/-!
It wouldn't really make sense to make an `Applicative` instance here. How would you write `pure` in
the `Applicative` instance? By taking a single value and plugging it in for total size _and_ the
master bedroom size _and_ the living room size? That wouldn't really make sense. And what would the
numBedrooms value be for the default? What would it mean to "chain" two of these objects together?
If you can't answer these questions very well, then it suggests this type isn't really an
Applicative functor.
## SeqLeft and SeqRight
You may remember seeing the `SeqLeft` and `SeqRight` base types on `class Applicative` earlier.
These provide the `seqLeft` and `seqRight` operations which also have some handy notation
shorthands `<*` and `*>` repsectively. Where: `x <* y` evaluates `x`, then `y`, and returns the
result of `x` and `x *> y` evaluates `x`, then `y`, and returns the result of `y`.
To make it easier to remember, notice that it returns that value that the `<*` or `*>` notation is
pointing at. For example:
-/
#eval (some 1) *> (some 2) -- Some 2
#eval (some 1) <* (some 2) -- Some 1
/-!
So these are a kind of "discard" operation. Run all the actions, but only return the values that you
care about. It will be easier to see these in action when you get to full Monads, but they are used
heavily in the Lean `Parsec` parser combinator library where you will find parsing functions like
this one which parses the XML declaration `<?xml version="1.0" encoding='utf-8' standalone="yes">`:
```lean
def XMLdecl : Parsec Unit := do
skipString "<?xml"
VersionInfo
optional EncodingDecl *> optional SDDecl *> optional S *> skipString "?>"
```
But you will need to understand full Monads before this will make sense.
## Lazy Evaluation
Diving a bit deeper, (you can skip this and jump to the [Applicative
Laws](laws.lean.md#what-are-the-applicative-laws) if don't want to dive into this implementation detail right
now). But, if you write a simple `Option` example `(.*.) <$> some 4 <*> some 5` that produces `some 20`
using `Seq.seq` you will see somthing interesting:
-/
#eval Seq.seq ((.*.) <$> some 4) (fun (_ : Unit) => some 5) -- some 20
/-!
This may look a bit combersome, specifically, why did we need to invent this funny looking function
`fun (_ : Unit) => (some 5)`?
Well if you take a close look at the type class definition:
```lean
class Seq (f : Type u → Type v) where
seq : {α β : Type u} → f (α → β) → (Unit → f α) → f β
```
You will see this function defined here: `(Unit → f α)`, this is a function that takes `Unit` as input
and produces the output of type `f α` where `f` is the container type `Type u -> Type v`, in this example `Option`
and `α` is the element type `Nat`, so `fun (_ : Unit) => some 5` matches this definition because
it is taking an input of type Unit and producing `some 5` which is type `Option Nat`.
The that `seq` is defined this way is because Lean is an eagerly evaluated language
(call-by-value), you have to use this kind of Unit function whenever you want to explicitly delay
evaluation and `seq` wants that so it can eliminate unnecessary function evaluations whenever
possible.
Fortunately the `<*>` infix notation hides this from you by creating this wrapper function for you.
If you look up the notation using F12 in VS Code you will find it contains `(fun _ : Unit => b)`.
Now to complete this picture you will find the default implementation of `seq` on the Lean `Monad`
type class:
```lean
class Monad (m : Type u → Type v) extends Applicative m, Bind m where
seq f x := bind f fun y => Functor.map y (x ())
```
Notice here that `x` is the `(Unit → f α)` function, and it is calling that function by passing the
Unit value `()`, which is the Unit value (Unit.unit). All this just to ensure delayed evaluation.
## How do Applicatives help with Monads?
Applicatives are helpful for the same reasons as functors. They're a relatively simple abstract
structure that has practical applications in your code. Now that you understand how chaining
operations can fit into a structure definition, you're in a good position to start learning about
[Monads](monads.lean.md)!
-/

166
doc/monads/except.lean Normal file
View File

@@ -0,0 +1,166 @@
/-!
# Except
The `Except` Monad adds exception handling behavior to your functions. Exception handling
in other languages like Python or Java is done with a built in `throw` method that you
can use anywhere. In `Lean` you can only `throw` an exception when your function is
executing in the context of an `Except` monad.
-/
def divide (x y: Float): Except String Float :=
if y == 0 then
throw "can't divide by zero"
else
pure (x / y)
#eval divide 5 2 -- Except.ok 2.500000
#eval divide 5 0 -- Except.error "can't divide by zero"
/-!
Just as the `read` operation was available from the `ReaderM` monad and the `get` and `set`
operations came with the `StateM` monad, here you can see a `throw` operation is provided by the
`Except` monad.
So in Lean, `throw` is not available everywhere like it is in most imperative programming languages.
You have to declare your function can throw by changing the type signature to `Except String Float`.
This creates a function that might return an error of type `String` or it might return a value of
type `Float` in the non-error case.
Once your function is monadic you also need to use the `pure` constructor of the `Except` monad to
convert the pure non-monadic value `x / y` into the required `Except` object. See
[Applicatives](applicatives.lean.md) for details on `pure`.
Now this return typing would get tedious if you had to include it everywhere that you call this
function, however, Lean type inference can clean this up. For example, you can define a test
function can calls the `divide` function and you don't need to say anything here about the fact that
it might throw an error, because that is inferred:
-/
def test := divide 5 0
#check test -- Except String Float
/-!
Notice the Lean compiler infers the required `Except String Float` type information for you.
And now you can run this test and get the expected exception:
-/
#eval test -- Except.error "can't divide by zero"
/-!
## Chaining
Now as before you can build a chain of monadic actions that can be composed together using `bind (>>=)`:
-/
def square (x : Float) : Except String Float :=
if x >= 100 then
throw "it's absolutely huge"
else
pure (x * x)
#eval divide 6 2 >>= square -- Except.ok 9.000000
#eval divide 6 0 >>= square -- Except.error "can't divide by zero"
#eval divide 100 1 >>= square -- Except.error "it's absolutely huge"
def chainUsingDoNotation := do
let r divide 6 0
square r
#eval chainUsingDoNotation -- Except.error "can't divide by zero"
/-!
Notice in the second `divide 6 0` the exception from that division was nicely propagated along
to the final result and the square function was pretty much ignored in that case.
Remember also that you can chain the actions with implicit binding by using the `do` notation
as you see in the `chainUsingDoNotation` function above.
## Try/Catch
Now with all good exception handling you also want to be able to catch exceptions so your program
can try continue on or do some error recovery task, which you can do like this:
-/
def testCatch :=
try
let r divide 8 0 -- 'r' is type Float
pure (toString r)
catch e =>
pure s!"Caught exception: {e}"
#check testCatch -- Except String String
/-!
Note that the type inferred by Lean for this function is `Except String String` so unlike the
`test` function earlier, this time Lean type inference has figured out that since the pure
value `(toString r)` is of type `String`, then this function must have type `Except String String`
so you don't have to explicitly state this. You can always hover your mouse over `testCatch`
or use `#check testCatch` to query Lean interactively to figure out what type inference
has decided. Lean type inference makes life easy for you, so it's good to use it
when you can.
You can now see the try/catch working in this eval:
-/
#eval testCatch -- Except.ok "Caught exception: can't divide by zero"
/-!
Notice the `Caught exception:` wrapped message is returned, and that it is returned as an
`Except.ok` value, meaning `testCatch` eliminated the error result as expected.
So you've interleaved a new concept into your functions (exception handling) and the compiler is still
able to type check everything just as well as it does for pure functions and it's been able to infer
some things along the way to make it even easier to manage.
Now you might be wondering why `testCatch` doesn't infer the return type `String`? Lean does this as a
convenience since you could have a rethrow in or after the catch block. If you really want to stop
the `Except` type from bubbling up you can unwrap it like this:
-/
def testUnwrap : String := Id.run do
let r divide 8 0 -- r is type Except String Float
match r with
| .ok a => toString a -- 'a' is type Float
| .error e => s!"Caught exception: {e}"
#check testUnwrap -- String
#eval testUnwrap -- "Caught exception: can't divide by zero"
/-!
The `Id.run` function is a helper function that executes the `do` block and returns the result where
`Id` is the _identity monad_. So `Id.run do` is a pattern you can use to execute monads in a
function that is not itself monadic.
## Monadic functions
You can also write functions that are designed to operate in the context of a monad.
These functions typically end in upper case M like `List.forM` used below:
-/
def validateList (x : List Nat) (max : Nat): Except String Unit := do
x.forM fun a => do
if a > max then throw "illegal value found in list"
#eval validateList [1, 2, 5, 3, 8] 10 -- Except.ok ()
#eval validateList [1, 2, 5, 3, 8] 5 -- Except.error "illegal value found in list"
/-!
Notice here that the `List.forM` function passes the monadic context through to the inner function
so it can use the `throw` function from the `Except` monad.
The `List.forM` function is defined like this where `[Monad m]` means "in the context of a monad `m`":
-/
def forM [Monad m] (as : List α) (f : α m PUnit) : m PUnit :=
match as with
| [] => pure
| a :: as => do f a; List.forM as f
/-!
## Summary
Now that you know all these different monad constructs, you might be wondering how you can combine
them. What if there was some part of your state that you wanted to be able to modify (using the
State monad), but you also needed exception handling. How can you get multiple monadic capabilities
in the same fuunction. To learn the answer, head to [Monad Transformers](transformers.lean.md).
-/

227
doc/monads/functors.lean Normal file
View File

@@ -0,0 +1,227 @@
/-!
# Functor
A `Functor` is any type that can act as a generic container that allows you to transform the
underlying values inside the container using a function, so that the values are all updated, but the
structure of the container is the same. This is called "mapping".
A List is one of the most basic examples of a `Functor`.
A list contains zero or more elements of the same, underlying type. When you `map` a function over
a list, you create a new list with the same number of elements, where each has been transformed by
the function:
-/
#eval List.map (λ x => toString x) [1,2,3] -- ["1", "2", "3"]
-- you can also write this using dot notation on the List object
#eval [1,2,3].map (λ x => toString x) -- ["1", "2", "3"]
/-!
Here we converted a list of natural numbers (Nat) to a list of strings where the lambda function
here used `toString` to do the transformation of each element. Notice that when you apply `map` the
"structure" of the object remains the same, in this case the result is always a `List` of the same
size.
Note that in Lean a lambda function can be written using `fun` keyword or the unicode
symbol `λ` which you can type in VS code using `\la `.
List has a specialized version of `map` defined as follows:
-/
def map (f : α β) : List α List β
| [] => []
| a::as => f a :: map f as
/-!
This is a very generic `map` function that can take any function that converts `(α → β)` and use it
to convert `List α → List β`. Notice the function call `f a` above, this application of `f` is
producing the converted items for the new list.
Let's look at some more examples:
-/
-- List String → List Nat
#eval ["elephant", "tiger", "giraffe"].map (fun s => s.length)
-- [8, 5, 7]
-- List Nat → List Float
#eval [1,2,3,4,5].map (fun s => (s.toFloat) ^ 3.0)
-- [1.000000, 8.000000, 27.000000, 64.000000, 125.000000]
--- List String → List String
#eval ["chris", "david", "mark"].map (fun s => s.capitalize)
-- ["Chris", "David", "Mark"]
/-!
Another example of a functor is the `Option` type. Option contains a value or nothing and is handy
for code that has to deal with optional values, like optional command line arguments.
Remember you can construct an Option using the type constructors `some` or `none`:
-/
#check some 5 -- Option Nat
#eval some 5 -- some 5
#eval (some 5).map (fun x => x + 1) -- some 6
#eval (some 5).map (fun x => toString x) -- some "5"
/-!
Lean also provides a convenient short hand syntax for `(fun x => x + 1)`, namely `(· + 1)`
using the middle dot unicode character which you can type in VS code using `\. `.
-/
#eval (some 4).map (· * 5) -- some 20
/-!
The `map` function preserves the `none` state of the Option, so again
map preserves the structure of the object.
-/
def x : Option Nat := none
#eval x.map (fun x => toString x) -- none
#check x.map (fun x => toString x) -- Option String
/-!
Notice that even in the `none` case it has transformed `Option Nat` into `Option String` as
you see in the `#check` command.
## How to make a Functor Instance?
The `List` type is made an official `Functor` by the following type class instance:
-/
instance : Functor List where
map := List.map
/-!
Notice all you need to do is provide the `map` function implementation. For a quick
example, let's supposed you create a new type describing the measurements of a home
or apartment:
-/
structure LivingSpace (α : Type) where
totalSize : α
numBedrooms : Nat
masterBedroomSize : α
livingRoomSize : α
kitchenSize : α
deriving Repr, BEq
/-!
Now you can construct a `LivingSpace` in square feet using floating point values:
-/
abbrev SquareFeet := Float
def mySpace : LivingSpace SquareFeet :=
{ totalSize := 1800, numBedrooms := 4, masterBedroomSize := 500,
livingRoomSize := 900, kitchenSize := 400 }
/-!
Now, suppose you want anyone to be able to map a `LivingSpace` from one type of measurement unit to
another. Then you would provide a `Functor` instance as follows:
-/
def LivingSpace.map (f : α β) (s : LivingSpace α) : LivingSpace β :=
{ totalSize := f s.totalSize
numBedrooms := s.numBedrooms
masterBedroomSize := f s.masterBedroomSize
livingRoomSize := f s.livingRoomSize
kitchenSize := f s.kitchenSize }
instance : Functor LivingSpace where
map := LivingSpace.map
/-!
Notice this functor instance takes `LivingSpace` and not the fully qualified type `LivingSpace SquareFeet`.
Notice below that `LivingSpace` is a function from Type to Type. For example, if you give it type `SquareFeet`
it gives you back the fully qualified type `LivingSpace SquareFeet`.
-/
#check LivingSpace -- Type → Type
/-!
So the `instance : Functor` then is operating on the more abstract, or generic `LivingSpace` saying
for the whole family of types `LivingSpace α` you can map to `LivingSpace β` using the generic
`LivingSpace.map` map function by simply providing a function that does the more primitive mapping
from `(f : α → β)`. So `LivingSpace.map` is a sort of function applicator.
This is called a "higher order function" because it takes a function as input
`(α → β)` and returns another function as output `F α → F β`.
Notice that `LivingSpace.map` applies a function `f` to convert the units of all the LivingSpace
fields, except for `numBedrooms` which is a count (and therefore is not a measurement that needs
converting).
So now you can define a simple conversion function, let's say you want square meters instead:
-/
abbrev SquareMeters := Float
def squareFeetToMeters (ft : SquareFeet ) : SquareMeters := (ft / 10.7639104)
/-!
and now bringing it all together you can use the simple function `squareFeetToMeters` to map
`mySpace` to square meters:
-/
#eval mySpace.map squareFeetToMeters
/-
{ totalSize := 167.225472,
numBedrooms := 4,
masterBedroomSize := 46.451520,
livingRoomSize := 83.612736,
kitchenSize := 37.161216 }
-/
/-!
Lean also defines custom infix operator `<$>` for `Functor.map` which allows you to write this:
-/
#eval (fun s => s.length) <$> ["elephant", "tiger", "giraffe"]
#eval (fun x => x + 1) <$> (some 5) -- some 6
/-!
Note that the infix operator is left associative which means it binds more tightly to the
function on the left than to the expression on the right, this means you can often drop the
parentheses on the right like this:
-/
#eval (fun x => x + 1) <$> some 5 -- some 6
/-!
Note that Lean lets you define your own syntax, so `<$>` is nothing special.
You can define your own infix operator like this:
-/
infixr:100 " doodle " => Functor.map
#eval (· * 5) doodle [1, 2, 3] -- [5, 10, 15]
/-!
Wow, this is pretty powerful. By providing a functor instance on `LivingSpace` with an
implementation of the `map` function it is now super easy for anyone to come along and
transform the units of a `LivingSpace` using very simple functions like `squareFeetToMeters`. Notice
that squareFeetToMeters knows nothing about `LivingSpace`.
## How do Functors help with Monads ?
Functors are an abstract mathematical structure that is represented in Lean with a type class. The
Lean functor defines both `map` and a special case for working on constants more efficiently called
`mapConst`:
```lean
class Functor (f : Type u → Type v) : Type (max (u+1) v) where
map : {α β : Type u} → (α → β) → f α → f β
mapConst : {α β : Type u} → α → f β → f α
```
Note that `mapConst` has a default implementation, namely:
`mapConst : {α β : Type u} → α → f β → f α := Function.comp map (Function.const _)` in the `Functor`
type class. So you can use this default implementation and you only need to replace it if
your Functors has a more specialized variant than this which is more performant.
In general then, a functor is a function on types `F : Type u → Type v` equipped with an operator
called `map` such that if you have a function `f` of type `α → β` then `map f` will convert your
container type from `F α → F β`. This corresponds to the category-theory notion of
[functor](https://en.wikipedia.org/wiki/Functor) in the special case where the category is the
category of types and functions between them.
Understanding abstract mathematical structures is a little tricky for most people. So it helps to
start with a simpler idea like functors before you try to understand monads. Building on
functors is the next abstraction called [Applicatives](applicatives.lean.md).
-/

63
doc/monads/intro.md Normal file
View File

@@ -0,0 +1,63 @@
# Monads
Monads are used heavily in Lean, as they are also in Haskell. Monads come from the wonderful world
of [Category Theory](https://en.wikipedia.org/wiki/Monad_%28category_theory%29).
Monads in Lean are so similar to Haskell that this introduction to monads is heavily based on the
similar chapter of the [Monday Morning Haskell](https://mmhaskell.com/monads/). Many thanks to
the authors of that material for allowing it to reused it here.
Monads build on the following fundamental type classes which you will need to understand
first before fully understanding monads. Shown in light blue are some concrete functors
and monads that will also be covered in this chapter:
![image](../images/monads.svg)
This chapter is organized to give you a bottom up introduction to monads, starting with functors and
applicative functors, you'll get an intuition for how these abstract structures work in Lean. Then
you'll dive into monads and learn how to use some of the most useful built-in ones.
## [Functor](functors.lean.md)
A functor is a type class that provides a map function and the map function is something many
people are already familiar with so this should be easy to follow. Here you will see some
concrete examples in action with `List` and `Option`.
## [Applicative Functors](applicatives.lean.md)
Applicatives are a little more difficult to understand than functors, but their functionality can
still be summed up in a couple simple functions. Here you will learn how to create an
`Applicative List` and a completely custom `Applicative` type.
## [Monads Tutorial](monads.lean.md)
Now that you have an intuition for how abstract structures work, you'll examine some of the problems
that functors and applicative functors don't help you solve. Then you'll lean the specifics of how
to actually use monads with some examples using the `Option` monad and the all important `IO` monad.
## [Reader Monads](readers.lean.md)
Now that you understand the details of what makes a monadic structure work, in this section, you'll
learn about one of the most useful built in monads `ReaderM`, which gives your programs a
global read-only context.
## [State Monad](states.lean.md)
This section introduces the `StateM` monad. This monad allows you to access a particular type that you can
both read from and write to. It opens the door to fully stateful programming, allowing you to do many
of the things a function programming language supposedly "can't" do.
## [Except Monad](except.lean.md)
Similar to the `Option` monad the `Except` monad allows you to change the signature of a function so
that it can return an `ok` value or an `error` and it makes available the classic exception handling
operations `throw/try/catch` so that your programs can do monad-based exception handling.
## [Monad Transformers](transformers.lean.md)
Now that you are familiar with all the above monads it is time to answer the question of how you can
make them work together. After all, there are definitely times when you need multiple kinds of
monadic behavior. This section introduces the concept of monad transformers, which allow you to
combine multiple monads into one.
## [Monad Laws](laws.lean.md)
This section examines what makes a monad a monad. After all, can't you just implement these type
classes any way you want and write a "monad" instance? Starting back with functors and applicative
functors, you'll learn that all these structures have "laws" that they are expected to obey with
respect to their behavior. You can make instances that don't follow these laws. But you do so at
your peril, as other programmers will be very confused when they try to use them.

318
doc/monads/laws.lean Normal file
View File

@@ -0,0 +1,318 @@
/-!
# Monad Laws
In the previous sections you learned how to use [Functors](functors.lean.md),
[Applicatives](applicatives.lean.md), and [Monads](monads.lean.md), and you played with some useful
instances including [Option](monads.lean.md), [IO](monads.lean.md), [Reader](readers.lean.md),
[State](states.lean.md) and [Except](except.lean.md) and you learned about composition using [Monad
Transformers](transformers.lean.md).
So far, you've learned the concrete details you need in order to _use_ monads in your Lean programs.
But there's still one more important concept you need if you want to _create_ new functors,
applicatives and monads. Namely, the notion of _structural "laws"_ -- rules that these type
classes should follow in order to meet other programmers' expectations about your code.
## Life without Laws
Remember Lean represents each of these abstract structures by a type class. Each of these type classes
has one or two main functions. So, as long as you implement those functions and it type checks, you
have a new functor, applicative, or monad, right?
Well not quite. Yes, your program will compile and you'll be able to use the instances. But this
doesn't mean your instances follow the mathematical constructs. If they don't, your instances won't
fulfill other programmers' expectations. Each type class has its own "laws". For instance, suppose
you have the following Point Functor:
-/
structure Point (α : Type) where
x : α
y : α
deriving Repr, BEq
def Point.map (f : α β) (s : Point α) : Point β :=
{ x := f s.y, -- an example of something weird
y := f s.x }
instance : Functor Point where
map := Point.map
#eval (·+2) <$> (Point.mk 1 2) -- { x := 4, y := 3 }
/-!
This Point does something weird, when you `map` it because it transposes the `x` and `y` coordinates
which is not what other people would expect from a `map` function. In fact, it breaks the rules
as you will see below.
## What are the Functor laws?
Functors have two laws: the _identity_ law, and the _composition_ law. These laws express behaviors that
your functor instances should follow. If they don't, other programmers will be very confused at the
effect your instances have on their program. Many structures have similar laws, including monads.
The identity law says that if you "map" the identity function (`id`) over your functor, the
resulting functor should be the same. A succinct way of showing this on a `List` functor is:
-/
def list1 := [1,2,3]
#eval id <$> list1 == list1 -- true
/-!
Now let's try the same test on the `Point` functor:
-/
def p1 : Point Nat := (Point.mk 1 2)
#eval id <$> p1 == p1 -- false
/-!
Oh, and look while the List is behaving well, the `Point` functor fails this identity test.
The _composition_ law says that if you "map" two functions in succession over a functor, this
should be the same as "composing" the functions and simply mapping that one super-function over the
functor. In Lean you can compose two functions using `Function.comp f g` (or the syntax `f ∘ g`,
which you can type in VS code using `\o `) and you will get the same results from both of these
showing that the composition law holds for `List Nat`:
-/
def double (x : Nat) := x + x
def square (x : Nat) := x * x
#eval double <$> (square <$> list1) -- [2, 8, 18]
#eval (double <$> (square <$> list1)) == ((double square) <$> list1) -- true
-- ok, what about the Point class?
#eval double <$> (square <$> p1) -- { x := 2, y := 8 }
#eval (double square) <$> p1 -- { x := 8, y := 2 }
#eval double <$> (square <$> p1) == (double square) <$> p1 -- false
/-!
Note that composition also fails on the bad `Point` because the x/y transpose.
As you can see this bad `Point` implementation violates both of the functor laws. In this case it
would not be a true functor. Its behavior would confuse any other programmers trying to use it. You
should take care to make sure that your instances make sense. Once you get a feel for these type
classes, the likelihood is that the instances you'll create will follow the laws.
You can also write a bad functor that passes one law but not the other like this:
-/
def bad_option_map {α β : Type u} : (α β) Option α Option β
| _, _ => none
instance : Functor Option where
map := bad_option_map
def t1 : Option Nat := some 10
#eval id <$> t1 == t1 -- false
#eval double <$> (square <$> t1) == (double square) <$> t1 -- true
/-!
This fails the id law but obeys the composition law. Hopefully this explains the value of these
laws, and you don't need to see any more bad examples!
## What are the Applicative Laws?
While functors have two laws, applicatives have four laws:
- Identity
- Homomorphism
- Interchange
- Composition
### Identity
`pure id <*> v = v`
Applying the identity function through an applicative structure should not change the underlying
values or structure. For example:
-/
instance : Applicative List where
pure := List.pure
seq f x := List.bind f fun y => Functor.map y (x ())
#eval pure id <*> [1, 2, 3] -- [1, 2, 3]
/-!
The `pure id` statement here is wrapping the identity function in an applicative structure
so that you can apply that over the container `[1, 2, 3]` using the Applicative `seq` operation
which has the notation `<*>`.
To prove this for all values `v` and any applicative `m` you can write this theorem:
-/
example [Applicative m] [LawfulApplicative m] (v : m α) :
pure id <*> v = v :=
by simp -- Goals accomplished 🎉
/-!
### Homomorphism
`pure f <*> pure x = pure (f x)`
Suppose you wrap a function and an object in pure. You can then apply the wrapped function over the
wrapped object. Of course, you could also apply the normal function over the normal object, and then
wrap it in pure. The homomorphism law states these results should be the same.
For example:
-/
def x := 1
def f := (· + 2)
#eval pure f <*> pure x = (pure (f x) : List Nat) -- true
/-!
You should see a distinct pattern here. The overriding theme of almost all these laws is that these
`Applicative` types should behave like normal containers. The `Applicative` functions should not
have any side effects. All they should do is facilitate the wrapping, unwrapping, and transformation
of data contained in the container resulting in a new container that has the same structure.
### Interchange
`u <*> pure y = pure (. y) <*> u`.
This law is is a little more complicated, so don't sweat it too much. It states that the order that
you wrap things shouldn't matter. One the left, you apply any applicative `u` over a pure wrapped
object. On the right, you first wrap a function applying the object as an argument. Note that `(·
y)` is short hand for: `fun f => f y`. Then you apply this to the first applicative `u`. These
should be the same.
For example:
-/
def y := 4
def g : List (Nat Nat) := [(· + 2)]
#eval g <*> pure y = pure (· y) <*> g -- true
/-!
You can prove this with the following theorem:
-/
example [Applicative m] [LawfulApplicative m] (u : m (α β)) (y : α) :
u <*> pure y = pure (· y) <*> u :=
by simp [pure_seq] -- Goals accomplished 🎉
/-!
### Composition:
`u <*> v <*> w = u <*> (v <*> w)`
This final applicative law mimics the second functor law. It is a composition law. It states that
function composition holds across applications within the applicative:
For example:
-/
def u := [1, 2]
def v := [3, 4]
def w := [5, 6]
#eval pure (·+·+·) <*> u <*> v <*> w
-- [9, 10, 10, 11, 10, 11, 11, 12]
#eval let grouping := pure (·+·) <*> v <*> w
pure (·+·) <*> u <*> grouping
-- [9, 10, 10, 11, 10, 11, 11, 12]
/-!
To test composition you see the separate grouping `(v <*> w)` then that can be used in the outer
sequence `u <*> grouping` to get the same final result `[9, 10, 10, 11, 10, 11, 11, 12]`.
## What are the Monad Laws?
Monads have three laws:
- Left Identity
- Right Identity
- Associativity
### Left Identity
Identity laws for monads specify that `pure` by itself shouldn't really change anything about the
structure or its values.
Left identity is `x >>= pure = x` and is demonstrated by the following examples on a monadic `List`:
-/
instance : Monad List where
pure := List.pure
bind := List.bind
#eval ["apple", "orange"] >>= pure -- ["apple", "orange"]
#eval [1,2,3] >>= pure -- [1,2,3]
/-!
### Right Identity
Right identity is `pure x >>= f = f x` and is demonstrated by the following example:
-/
def h (x : Nat) : Option Nat := some (x + 1)
def z := 5
#eval pure z >>= h -- some 6
#eval h z -- some 6
#eval pure z >>= h = h x -- true
/-!
So in this example, with this specific `z` and `h`, you see that the rule holds true.
### Associativity
The associativity law is written as:
```lean,ignore
x >>= f >>= g = x >>= (λ x => f x >>= g)
```
where `(x : m α)` and `(f : α → m β)` and `(g : β → m γ)`.
The associativity law is difficult to parse like some of the applicative laws, but what it is saying
is that if you change the grouping of `bind` operations, you should still get the same result.
This law has a parallel structure to the other composition laws.
You can see this in action in the following rewrite of `runOptionFuncsBind` from [monads](monads.lean.md):
-/
def optionFunc1 : String -> Option Nat
| "" => none
| str => some str.length
def optionFunc2 (i : Nat) : Option Float :=
if i % 2 == 0 then none else some (i.toFloat * 3.14159)
def optionFunc3 (f : Float) : Option (List Nat) :=
if f > 15.0 then none else some [f.floor.toUInt32.toNat, f.ceil.toUInt32.toNat]
def runOptionFuncsBind (input : String) : Option (List Nat) :=
optionFunc1 input >>= optionFunc2 >>= optionFunc3
def runOptionFuncsBindGrouped (input : String) : Option (List Nat) :=
optionFunc1 input >>= (λ x => optionFunc2 x >>= optionFunc3)
#eval runOptionFuncsBind "big" -- some [9, 10]
#eval runOptionFuncsBindGrouped "big" -- some [9, 10]
/-!
Notice here we had to insert a `λ` function just like the definition says: `(λ x => f x >>= g)`.
This is because unlike applicatives, you can't resolve the structure of later operations without the
results of earlier operations quite as well because of the extra context monads provide. But you can
still group their later operations into composite functions taking their inputs from earlier on, and
the result should be the same.
## Summary
While these laws may be a bit difficult to understand just by looking at them, the good news is that
most of the instances you'll make will naturally follow the laws so long as you keep it simple, so
you shouldn't have to worry about them too much.
There are two main ideas from all the laws:
1. Applying the identity or pure function should not change the underlying values or structure.
1. It should not matter what order you group operations in. Another way to state this is function
composition should hold across your structures.
Following these laws will ensure other programmers are not confused by the bahavior of your
new functors, applicatives and monads.
-/

300
doc/monads/monads.lean Normal file
View File

@@ -0,0 +1,300 @@
/-!
# Monads
Building on [Functors](functors.lean.md) and [Applicatives](applicatives.lean.md) we can now
introduce [monads](https://en.wikipedia.org/wiki/Monad_%28category_theory%29).
A monad is another type of abstract, functional structure. Let's explore what makes it different
from the first two structures.
## What is a Monad?
A monad is a computational context. It provides a structure that allows you to chain together
operations that have some kind of shared state or similar effect. Whereas pure functional code can
only operate on explicit input parameters and affect the program through explicit return values,
operations in a monad can affect other computations in the chain implicitly through side effects,
especially modification of an implicitly shared value.
## How are monads represented in Lean?
Like functors and applicatives, monads are represented with a type class in Lean:
```lean,ignore
class Monad (m : Type u → Type v) extends Applicative m, Bind m where
```
Just as every applicative is a functor, every monad is also an applicative and there's one more new
base type class used here that you need to understand, namely, `Bind`.
```lean,ignore
class Bind (f : Type u → Type v) where
bind : {α β : Type u} → f α → (α → f β) → f β
```
The `bind` operator also has infix notation `>>=` where `x >>= g` represents the result of executing
`x` to get a value of type `f α` then unwrapping the value `α` from that and passing it to function
`g` of type `α → f β` returning the result of type `f β` where `f` is the target structure type
(like `Option` or List)
This `bind` operation looks similar to the other ones you've seen so far, if you put them all
together `Monad` has the following operations:
```lean,ignore
class Monad (f : Type u → Type v) extends Applicative f, Bind f where
pure {α : Type u} : α → f α
map : {α β : Type u} → (α → β) → f α → f β
seq : {α β : Type u} → f (α → β) → (Unit → f α) → f β
bind : {α β : Type u} → f α → (α → f β) → f β
...
```
Notice `Monad` also contains `pure` it must also have a "default" way to wrap a value in the
structure.
The `bind` operator is similar to the applicative `seq` operator in that it chains two operations,
with one of them being function related. Notice that `bind`, `seq` and `map` all take a function of
some kind. Let's examine those function types:
- map: `(α → β)`
- seq: `f (α → β)`
- bind: `(α → f β)`
So `map` is a pure function, `seq` is a pure function wrapped in the structure, and `bind` takes a
pure input but produces an output wrapped in the structure.
Note: we are ignoring the `(Unit → f α)` function also used by `seq` in this comparison, since that
was explained in [Applicatives Lazy Evaluation](applicatives.lean.md#lazy-evaluation).
## Basic Monad Example
Just as `Option` is a functor and an applicative functor, it is also a monad! Let's start with how
`Option` implements the Monad type class.
-/
instance : Monad Option where
pure := Option.some
bind := Option.bind
/-!
where:
```lean,ignore
def Option.bind : Option α → (α → Option β) → Option β
| none, _ => none
| some a, f => f a
```
> **Side note**: this function definition is using a special shorthand syntax in Lean where the `:=
match a, b with` code can be collapsed away. To make this more clear consider the following simpler
example, where `Option.bind` is using the second form like `bar`:
-/
def foo (x : Option Nat) (y : Nat) : Option Nat :=
match x, y with
| none, _ => none
| some x, y => some (x + y)
def bar : Option Nat Nat Option Nat
| none, _ => none
| some x, y => some (x + y)
#eval foo (some 1) 2 -- some 3
#eval bar (some 1) 2 -- some 3
/-!
What is important is that `Option.bind` is using a `match` statement to unwrap the input value
`Option α`, if it is `none` then it does nothing and returns `none`, if it has a value of type `α`
then it applies the function in the second argument `(α → Option β)` to this value, which is
the expression `f a` that you see in the line ` | some a, f => f a` above. The function
returns a result of type `Option β` which then becomes the return value for `bind`. So there
is no structure wrapping required on the return value since the input function already did that.
But let's bring in the definition of a monad. What does it mean to describe `Option` as a
computational context?
The `Option` monad encapsulates the context of failure. Essentially, the `Option` monad lets us
abort a series of operations whenever one of them fails. This allows future operations to assume
that all previous operations have succeeded. Here's some code to motivate this idea:
-/
def optionFunc1 : String -> Option Nat
| "" => none
| str => some str.length
def optionFunc2 (i : Nat) : Option Float :=
if i % 2 == 0 then none else some (i.toFloat * 3.14159)
def optionFunc3 (f : Float) : Option (List Nat) :=
if f > 15.0 then none else some [f.floor.toUInt32.toNat, f.ceil.toUInt32.toNat]
def runOptionFuncs (input : String) : Option (List Nat) :=
match optionFunc1 input with
| none => none
| some i => match optionFunc2 i with
| none => none
| some f => optionFunc3 f
#eval runOptionFuncs "big" -- some [9, 10]
/-!
Here you see three different functions that could fail. These are then combined in `runOptionFuncs`.
But then you have to use nested `match` expressions to check if the previous result succeeded. It
would be very tedious to continue this pattern much longer.
The `Option` monad helps you fix this. Here's what this function looks like using the `bind`
operator.
-/
def runOptionFuncsBind (input : String) : Option (List Nat) :=
optionFunc1 input >>= optionFunc2 >>= optionFunc3
#eval runOptionFuncsBind "big" -- some [9, 10]
/-!
It's much cleaner now! You take the first result and pass it into the second and third functions
using the `bind` operation. The monad instance handles all the failure cases so you don't have to!
Let's see why the types work out. The result of `optionFunc1` input is simply `Option Nat`. Then the
bind operator allows you to take this `Option Nat` value and combine it with `optionFunc2`, whose type
is `Nat → Option Float` The **bind operator resolves** these to an `Option Float`. Then you pass this
similarly through the bind operator to `optionFunc3`, resulting in the final type, `Option (List Nat)`.
Your functions will not always combine so cleanly though. This is where `do` notation comes into play.
This notation allows you to write monadic operations one after another, line-by-line. It almost makes
your code look like imperative programming. You can rewrite the above as:
-/
def runOptionFuncsDo (input : String) : Option (List Nat) := do
let i optionFunc1 input
let f optionFunc2 i
optionFunc3 f
#eval runOptionFuncsDo "big" -- some [9, 10]
/-!
The `←` operator used here is special. It effectively unwraps the value on the right-hand side from
the monad. This means the value `i` has type `Nat`, _even though_ the result of `optionFunc1` is
`Option Nat`. This is done using a `bind` operation under the hood.
> Note you can use `<-` or the nice unicode symbol `←` which you can type into VS code by typing
these characters `\l `. When you type the final space, `\l` is replaced with `←`.
Observe that we do not unwrap the final line of the computation. The function result is `Option
(List Nat)` which matches what `optionFunc3` returns. At first glance, this may look more complicated
than the `bind` example. However, it gives you a lot more flexibility, like mixing monadic and
non-monadic statements, using if then/else structures with their own local do blocks and so on. It
is particularly helpful when one monadic function depends on multiple previous functions.
## Example using List
You can easily make `List` into a monad with the following, since List already provides an
implementation of `pure` and `bind`.
-/
instance : Monad List where
pure := List.pure
bind := List.bind
/-!
Like you saw with the applicative `seq` operator, the `bind` operator applies the given function
to every element of the list. It is useful to look at the bind implementation for List:
-/
open List
def bind (a : List α) (b : α List β) : List β := join (map b a)
/-!
So `Functor.map` is used to apply the function `b` to every element of `a` but this would
return a whole bunch of little lists, so `join` is used to turn those back into a single list.
Here's an example where you use `bind` to convert a list of strings into a combined list of chars:
-/
#eval "apple".toList -- ['a', 'p', 'p', 'l', 'e']
#eval ["apple", "orange"] >>= String.toList
-- ['a', 'p', 'p', 'l', 'e', 'o', 'r', 'a', 'n', 'g', 'e']
/-!
## The IO Monad
The `IO Monad` is perhaps the most important monad in Lean. It is also one of the hardest monads to
understand starting out. Its actual implementation is too intricate to discuss when first learning
monads. So it is best to learn by example.
What is the **computational context** that describes the IO monad? IO operations can read
information from or write information to the terminal, file system, operating system, and/or
network. They interact with systems outside of your program. If you want to get user input, print a
message to the user, read information from a file, or make a network call, you'll need to do so
within the IO Monad.
The state of the world outside your program can change at virtually any moment, and so this IO
context is particularly special. So these IO operations are "side effects" which means you cannot
perform them from "pure" Lean functions.
Now, the most important job of pretty much any computer program is precisely to perform this
interaction with the outside world. For this reason, the root of all executable Lean code is a
function called main, with the type `IO Unit`. So every program starts in the IO monad!
When your function is `IO` monadic, you can get any input you need, call into "pure" code with the
inputs, and then output the result in some way. The reverse does not work. You cannot call into IO
code from pure code like you can call into a function that takes `Option` as input. Another way to
say this is you cannot invent an `IO` context out of thin air, it has to be given to you in your
`main` function.
Let's look at a simple program showing a few of the basic IO functions. It also uses `do` notation
to make the code read nicely:
-/
def main : IO Unit := do
IO.println "enter a line of text:"
let stdin IO.getStdin -- IO IO.FS.Stream (monadic)
let input stdin.getLine -- IO.FS.Stream → IO String (monadic)
let uppercased := input.toUpper -- String → String (pure)
IO.println uppercased -- IO Unit (monadic)
/-!
So, once again you can see that the `do` notation lets you chain a series of monadic actions.
`IO.getStdin` is of type `IO IO.FS.Stream` and `stdin.getLine` is of type `IO String`
and `IO.println` is of type `IO Unit`.
In between you see a non-monadic expression `let uppercased := input.toUpper` which is fine too.
A let statement can occur in any monad. Just as you could unwrap `i` from `Option Nat` to get the
inner Nat, you can use `←` to unwrap the result of `getLine` to get a String. You can then manipulate
this value using normal pure string functions like `toUpper`, and then you can pass the result to the
`IO.println` function.
This is a simple echo program. It reads a line from the terminal, and then prints the line back out
capitalized to the terminal. Hopefully it gives you a basic understanding of how IO works.
You can test this program using `lean --run` as follows:
```
> lean --run Main.lean
enter a line of text:
the quick brown fox
THE QUICK BROWN FOX
```
Here the user entered the string `the quick brown fox` and got back the uppercase result.
## What separates Monads from Applicatives?
The key that separates these is **context**. You cannot really determine the structure of
"future" operations without knowing the results of "past" operations, because the past can alter the
context in which the future operations work. With applicatives, you can't get the final function
result without evaluating everything, but you can determine the structure of how the operation will
take place. This allows some degree of parallelism with applicatives that is not generally possible
with monads.
## Conclusion
Hopefully you now have a basic level understanding of what a monad is. But perhaps some more
examples of what a "computational context" means would be useful to you. The Reader, State and
Except monads each provide a concrete and easily understood context that can be compared easily to
function parameters. You can learn more about those in [Reader monads](readers.lean.md),
[State monads](states.lean.md), and the [Except monad](except.lean.md).
-/

194
doc/monads/readers.lean Normal file
View File

@@ -0,0 +1,194 @@
/-!
# Readers
In the [previous section](monads.lean.md) you learned about the conceptual idea of monads. You learned
what they are, and saw how some common types like `IO` and `Option` work as monads. Now in this
part, you will be looking at some other useful monads. In particular, the `ReaderM` monad.
## How to do Global Variables in Lean?
In Lean, your code is generally "pure", meaning functions can only interact with the arguments
passed to them. This effectively means you cannot have global variables. You can have global
definitions, but these are fixed at compile time. If some user behavior might change them, you have
to wrap them in the `IO` monad, which means they can't be used from pure code.
Consider this example. Here, you want to have an `Environment` containing different parameters as a
global variable. However, you want to load these parameters from the process environment variables,
which requires the `IO` monad.
-/
structure Environment where
path : String
home : String
user : String
deriving Repr
def getEnvDefault (name : String): IO String := do
let val? IO.getEnv name
pure <| match val? with
| none => ""
| some s => s
def loadEnv : IO Environment := do
let path getEnvDefault "PATH"
let home getEnvDefault "HOME"
let user getEnvDefault "USER"
pure { path, home, user }
def func1 (e : Environment) : Float :=
let l1 := e.path.length
let l2 := e.home.length * 2
let l3 := e.user.length * 3
(l1 + l2 + l3).toFloat * 2.1
def func2 (env : Environment) : Nat :=
2 + (func1 env).floor.toUInt32.toNat
def func3 (env : Environment) : String :=
"Result: " ++ (toString (func2 env))
def main : IO Unit := do
let env loadEnv
let str := func3 env
IO.println str
#eval main -- Result: 7538
/-!
The only function actually using the environment is func1. However func1 is a pure function. This
means it cannot directly call loadEnv, an impure function in the IO monad. This means the
environment has to be passed through as a variable to the other functions, just so they can
ultimately pass it to func1. In a language with global variables, you could save env as a global
value in main. Then func1 could access it directly. There would be no need to have it as a parameter
to func1, func2 and func3. In larger programs, these "pass-through" variables can cause a lot of
headaches.
## The Reader Solution
The `ReaderM` monad solves this problem. It effectively creates a global read-only value of a
specified type. All functions within the monad can "read" the type. Let's look at how the `ReaderM`
monad changes the shape of this code. Now the functions **no longer need** to be given the
`Environment` as an explicit parameter, as they can access it through the monad.
-/
def readerFunc1 : ReaderM Environment Float := do
let env read
let l1 := env.path.length
let l2 := env.home.length * 2
let l3 := env.user.length * 3
return (l1 + l2 + l3).toFloat * 2.1
def readerFunc2 : ReaderM Environment Nat :=
readerFunc1 >>= (fun x => return 2 + (x.floor.toUInt32.toNat))
def readerFunc3 : ReaderM Environment String := do
let x readerFunc2
return "Result: " ++ toString x
def main2 : IO Unit := do
let env loadEnv
let str := readerFunc3.run env
IO.println str
#eval main2 -- Result: 7538
/-!
The `ReaderM` monad provides a `run` method and it is the `ReaderM` run method that takes the initial
`Environment` context. So here you see `main2` loads the environment as before, and estabilishes
the `ReaderM` context by passing `env` to the `run` method.
> **Side note 1**: The `return` statement used above also needs some explanation. The `return`
statement in Lean is closely related to `pure`, but a little different. First the similarity is that
`return` and `pure` both lift a pure value up to the Monad type. But `return` is a keyword so you do
not need to parenthesize the expression like you do when using `pure`. (Note: you can avoid
parentheses when using `pure` by using the `<|` operator like we did above in the initial
`getEnvDefault` function). Furthermore, `return` can also cause an early `return` in a monadic
function similar to how it can in an imperative language while `pure` cannot.
> So technically if `return` is the last statement in a function it could be replaced with `pure <|`,
but one could argue that `return` is still a little easier for most folks to read, just so long as
you understand that `return` is doing more than other languages, it is also wrapping pure values in
the monadic container type.
> **Side note 2**: If the function `readerFunc3` also took some explicit arguments then you would have
to write `(readerFunc3 args).run env` and this is a bit ugly, so Lean provides an infix operator
`|>` that eliminiates those parens so you can write `readerFunc3 args |>.run env` and then you can
chain multiple monadic actions like this `m1 args1 |>.run args2 |>.run args3` and this is the
recommended style. You will see this patten used heavily in Lean code.
The `let env ← read` expression in `readerFunc1` unwraps the environment from the `ReaderM` so we
can use it. Each type of monad might provide one or more extra functions like this, functions that
become available only when you are in the context of that monad.
Here the `readerFunc2` function uses the `bind` operator `>>=` just to show you that there are bind
operations happening here. The `readerFunc3` function uses the `do` notation you learned about in
[Monads](monads.lean.md) which hides that bind operation and can make the code look cleaner.
The `do` notation with `let x ← readerFunc2` is also calling the `bind` function under the covers,
so that you can access the unwrapped value `x` needed for the `toString x` conversion.
The important difference here to the earlier code is that `readerFunc3` and `readerFunc2` no longer
have an **explicit** Environment input parameter that needs to be passed along all the way to
`readerFunc1`. Instead, the `ReaderM` monad is taking care of that for you, which gives you the
illusion of something like global context where the context is now available to all functions that use
the `ReaderM` monad.
The above code also introduces an important idea. Whenever you learn about a monad "X", there's
often (but not always) a `run` function to execute that monad, and sometimes some additional
functions like `read` that interact with the monad context.
You might be wondering, how does the context actually move through the `ReaderM` monad? How can you
add an input argument to a function by modifying its return type? There is a special command in
Lean that will show you the reduced types:
-/
#reduce ReaderM Environment String -- Environment → String
/-!
And you can see here that this type is actually a function! It's a function that takes an
`Environment` as input and returns a `String`.
Now, remember in Lean that a function that takes an argument of type `Nat` and returns a `String`
like `def f (a : Nat) : String` is the same as this function `def f : Nat → String`. These are
exactly equal as types. Well this is being used by the `ReaderM` Monad to add an input argument to
all the functions that use the `ReaderM` monad and this is why `main` is able to start things off by
simply passing that new input argument in `readerFunc3 env`. So now that you know the implementation
details of the `ReaderM` monad you can see that what it is doing looks very much like the original
code we wrote at the beginning of this section, only it's taking a lot of the tedious work off your
plate and it is creating a nice clean separation between what your pure functions are doing, and the
global context idea that the `ReaderM` adds.
## withReader
One `ReaderM` function can call another with a modified version of the `ReaderM` context. You can
use the `withReader` function from the `MonadWithReader` typeclass to do this:
-/
def readerFunc3WithReader : ReaderM Environment String := do
let x withReader (λ env => { env with user := "new user" }) readerFunc2
return "Result: " ++ toString x
/-!
Here we changed the `user` in the `Environment` context to "new user" and then we
passed that modified context to `readerFunc2`.
So `withReader f m` executes monad `m` in the `ReaderM` context modified by `f`.
## Handy shortcut with (← e)
If you use the operator `←` in a let expression and the variable is only used once you can
eliminate the let expression and place the `←` operator in parentheses like this
call to loadEnv:
-/
def main3 : IO Unit := do
let str := readerFunc3 ( loadEnv)
IO.println str
/-!
## Conclusion
It might not seem like much has been accomplished with this `ReaderM Environment` monad, but you will
find that in larger code bases, with many different types of monads all composed together this
greatly cleans up the code. Monads provide a beautiful functional way of managing cross-cutting
concerns that would otherwise make your code very messy.
Now it's time to move on to [StateM Monad](states.lean.md) which is like a `ReaderM` that is
also updatable.
-/

252
doc/monads/states.lean Normal file
View File

@@ -0,0 +1,252 @@
import Lean.Data.HashMap
/-!
# State
In the [previous section](readers.lean.md), you learned about the `ReaderM` monad. Hopefully this gave you
a new perspective on Lean. It showed that, in fact, you _can_ have global variables of some sort;
you just need to encode them in the type signature somehow, and this is what monads are for! In this
part, you will explore the `StateM` monad, which is like a `ReaderM` only the state can also be updated.
## Motivating example: Tic Tac Toe
For this part, let's build a simple model for a Tic Tace Toe game. The main object is the `GameState`
data type containing several important pieces of information. First and foremost, it has the
"board", a map from 2D tile indices to the "Tile State" (X, O or empty). Then it also knows the
current player, and it has a random generator.
-/
open Std (HashMap)
abbrev TileIndex := Nat × Nat -- a 2D index
inductive TileState where
| TileEmpty | TileX | TileO
deriving Repr, BEq
inductive Player where
| XPlayer | OPlayer
deriving Repr, BEq
abbrev Board := HashMap TileIndex TileState
structure GameState where
board : Board
currentPlayer : Player
generator : StdGen
/-!
Let's think at a high level about how some of the game functions would work. You could, for
instance, have a function for selecting a random move. This would output a `TileIndex` to play and
alter the game's number generator. You would then make a move based on the selected move and the
current player. This would change the board state as well as swap the current player. In other
words, you have operations that depend on the current state of the game, but also need to **update
that state**.
## The StateM Monad to the Rescue
This is exactly the situation the `StateM` monad deals with. The `StateM` monad wraps computations in
the context of reading and modifying a global state object.
It is parameterized by a single type parameter `s`, the state type in use. So just like the `ReaderM`
has a single type you read from, the `StateM` has a single type you can both **read from and write
to**. There are three primary actions you can take within the `StateM`monad:
- **get** - retrieves the state, like Reader.read
- **set** - updates the state
- **modifyGet** - retrieves the state, then updates it
There is also a `run` function, similar to `run` on `ReaderM`. Like the `ReaderM` monad, you must
provide an initial state, in addition to the computation to run. `StateM` then produces two outputs:
the result of the computation combined with the final updated state.
If you wish to discard the final state and just get the computation's result, you can use
`run'` method instead. Yes in Lean, the apostraphe can be part of a name, you read this "run
prime", and the general naming convention is that the prime method discards something.
So for your Tic Tac Toe game, many of your functions will have a signature like `State GameState a`.
## Stateful Functions
Now you can examine some of the different functions mentioned above and determine their types.
You can, for instance, pick a random move:
-/
open TileState
def findOpen : StateM GameState (List TileIndex) := do
let game get
return game.board.toList.filterMap fun (i, x) => guard (x == TileEmpty) *> pure i
def chooseRandomMove : StateM GameState TileIndex := do
let game get
let openSpots findOpen
let gen := game.generator
let (i, gen') := randNat gen 0 (openSpots.length - 1)
set { game with generator := gen' }
return openSpots[i]!
/-!
This returns a `TileIndex` and modifies the random number generator stored in the `GameState`!
Notice you have a fun little use of the `Applicative.seqRight` operator `*>` in `findOpen`
as described in [Applicatives](applicatives.lean.md).
Now you can create the function that can make a move:
-/
open Player
def tileStateForPlayer : Player TileState
| XPlayer => TileX
| OPlayer => TileO
def nextPlayer : Player Player
| XPlayer => OPlayer
| OPlayer => XPlayer
def applyMove (i : TileIndex): StateM GameState Unit := do
let game get
let p := game.currentPlayer
let newBoard := game.board.insert i (tileStateForPlayer p)
set { game with currentPlayer := nextPlayer p, board := newBoard }
/-!
This updates the board in the `GameState` with the new tile, and then changes the current player,
providing no output (`Unit` return type).
So finally, you can combine these functions together with `do` notation, and it actually looks quite
clean! You don't need to worry about the side effects. The different monadic functions handle them.
Here's a sample of what your function might look like to play one turn of the game. At the end, it
returns a boolean determining if all the spaces have been filled.
-/
def isGameDone : StateM GameState Bool := do
return ( findOpen).isEmpty
def nextTurn : StateM GameState Bool := do
let i chooseRandomMove
applyMove i
isGameDone
/-!
To give you a quick test harness that runs all moves for both players you can run this:
-/
def initBoard : Board := Id.run do
let mut board := HashMap.empty
for i in [0:3] do
for j in [0:3] do
let t : TileIndex := (i, j)
board := board.insert t TileEmpty
board
def printBoard (board : Board) : IO Unit := do
let mut row : List String := []
for i in board.toList do
let s := match i.2 with
| TileEmpty => " "
| TileX => "X"
| TileO => "O"
row := row.append [s]
if row.length == 3 then
IO.println row
row := []
def playGame : StateM GameState Unit := do
while true do
let finished nextTurn
if finished then return
def main : IO Unit := do
let gen IO.stdGenRef.get
let (x, gen') := randNat gen 0 1
let gs := {
board := initBoard,
currentPlayer := if x = 0 then XPlayer else OPlayer,
generator := gen' }
let (_, g) := playGame |>.run gs
printBoard g.board
#eval main
-- [X, X, O]
-- [X, O, O]
-- [O, O, X]
/-!
Note that when you run the above code interactively the random number generator always starts in the
same place. But if you run `lean --run states.lean` then you will see randomness in the result.
## Implementation
It may be helpful to see how the `StateM` monad adds the input state and output state. If you look
at the reduced Type for `nextTurn`:
-/
#reduce StateM GameState Bool
-- GameState → Bool × GameState
/-!
So a function like `nextTurn` that might have just returned a `Bool` has been modified by the
`StateM` monad such that the initial `GameState` is passed in as a new input argument, and the output
value has been changed to the pair `Bool × GameState` so that it can return the pure `Bool` and the
updated `GameState`. This is why the call to `nextTurn` looks like this: `let (_, g) := nextTurn gs`.
This expression `(_, g)` conveniently breaks the pair up into 2 values, it doesn't care what the first
value is (hence the underscore `_`), but it does need the updated state `g` which you can then assign
back to the mutable `gs` variable to use next time around this loop.
It is also interesting to see how much work the `do` and `←` notation are doing for you. To
implement the `nextTurn` function without these you would have to write this, manually plumbing
the state all the way through:
-/
def nextTurnManually : StateM GameState Bool
| state =>
let (i, gs) := chooseRandomMove |>.run state
let (_, gs') := applyMove i |>.run gs
let (result, gs'') := isGameDone |>.run gs'
(result, gs'')
/-!
## StateM vs ReaderM
While `ReaderM` functions can use `withReader` to modify the context before calling another function,
`StateM` functions are a little more powerful, let's look at this function again:
```
def nextTurn : StateM GameState Bool := do
let i ← chooseRandomMove
applyMove i
isGameDone
```
In this function `chooseRandomMove` is modifying the state that `applyMove` is getting
and `chooseRandomMove` knows nothing about `applyMove`. So `StateM` functions can have this
kind of downstream effect outside their own scope, whereas, `withReader` cannot do that.
## State, IO and other languages
When thinking about Lean, it is often seen as a restriction that you can't have global variables or
`static` variables like you can with other languages like Python or C++. However, hopefully you see
now this isn't true. You can have a data type with exactly the same functionality as a Python class.
You would simply have many functions that can modify some global state using the `StateM` monad.
The difference is in Lean you simply put a label on these types of functions. You don't allow it to
happen for free anywhere in an uncontrolled fashion because that results in too many sleepless
nights debugging nasty code. You want to know when side effects can potentially happen, because
knowing when they can happen makes your code easier to reason about. In a Python class, many of the
methods won't actually need to modify the global state. But they could, which makes it harder to
debug them. In Lean you can simply make these pure functions, and the compiler will ensure they stay
pure and cannot modify any global state.
IO is the same way. It's not like you can't perform IO in Lean. Instead, you want to label the areas
where you can, to increase your certainty about the areas where you don't need to. When you know part of
your code cannot communicate with the outside world, you can be far more certain of its behavior.
The `StateM` monad is also a more disciplined way of managing side effects. Top level code could
call a `StateM` function multiple times with different independent initial states, even doing that
across multiple tasks in parallel and each of these cannot clobber the state belonging to other
tasks. Monadic code is more reusable than code that uses global variables.
## Summary
That wraps it up for the `StateM` monad! There is one more very useful monad that can be used to do
exception handling which will be covered in the [next section](except.lean.md).
-/

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