mirror of
https://github.com/leanprover/lean4.git
synced 2026-04-17 09:34:09 +00:00
Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b09d39a766 | ||
|
|
348ed9b3b0 | ||
|
|
f8b9610b74 | ||
|
|
3fc99eef10 | ||
|
|
b99356ebcf | ||
|
|
7e8a710ca3 | ||
|
|
621c558c13 | ||
|
|
490c79502b | ||
|
|
fed2f32651 | ||
|
|
5949ae8664 | ||
|
|
fe77e4d2d1 | ||
|
|
9b1426fd9c | ||
|
|
b6bfe019a1 | ||
|
|
748783a5ac | ||
|
|
df23b79c90 | ||
|
|
8156373037 | ||
|
|
75487a1bf8 | ||
|
|
559f6c0ae7 |
@@ -118,6 +118,7 @@ option(USE_LAKE "Use Lake instead of lean.mk for building core libs from languag
|
||||
option(USE_LAKE_CACHE "Use the Lake artifact cache for stage 1 builds (requires USE_LAKE)" OFF)
|
||||
|
||||
set(LEAN_EXTRA_OPTS "" CACHE STRING "extra options to lean (via lake or make)")
|
||||
set(LEAN_EXTRA_LAKE_OPTS "" CACHE STRING "extra options to lake")
|
||||
set(LEAN_EXTRA_MAKE_OPTS "" CACHE STRING "extra options to leanmake")
|
||||
set(LEANC_CC ${CMAKE_C_COMPILER} CACHE STRING "C compiler to use in `leanc`")
|
||||
|
||||
@@ -127,7 +128,7 @@ string(APPEND LEAN_EXTRA_OPTS " -Dbackward.do.legacy=false")
|
||||
# option used by the CI to fail on warnings
|
||||
option(WFAIL "Fail build if warnings are emitted by Lean" ON)
|
||||
if(WFAIL MATCHES "ON")
|
||||
string(APPEND LAKE_EXTRA_ARGS " --wfail")
|
||||
string(APPEND LEAN_EXTRA_LAKE_OPTS " --wfail")
|
||||
string(APPEND LEAN_EXTRA_MAKE_OPTS " -DwarningAsError=true")
|
||||
endif()
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ public theorem IsLinearOrder.of_ord {α : Type u} [LE α] [Ord α] [LawfulOrderO
|
||||
/--
|
||||
This lemma derives a `LawfulOrderLT α` instance from a property involving an `Ord α` instance.
|
||||
-/
|
||||
public instance LawfulOrderLT.of_ord (α : Type u) [Ord α] [LT α] [LE α] [LawfulOrderOrd α]
|
||||
public theorem LawfulOrderLT.of_ord (α : Type u) [Ord α] [LT α] [LE α] [LawfulOrderOrd α]
|
||||
(lt_iff_compare_eq_lt : ∀ a b : α, a < b ↔ compare a b = .lt) :
|
||||
LawfulOrderLT α where
|
||||
lt_iff a b := by
|
||||
@@ -96,7 +96,7 @@ public instance LawfulOrderLT.of_ord (α : Type u) [Ord α] [LT α] [LE α] [Law
|
||||
/--
|
||||
This lemma derives a `LawfulOrderBEq α` instance from a property involving an `Ord α` instance.
|
||||
-/
|
||||
public instance LawfulOrderBEq.of_ord (α : Type u) [Ord α] [BEq α] [LE α] [LawfulOrderOrd α]
|
||||
public theorem LawfulOrderBEq.of_ord (α : Type u) [Ord α] [BEq α] [LE α] [LawfulOrderOrd α]
|
||||
(beq_iff_compare_eq_eq : ∀ a b : α, a == b ↔ compare a b = .eq) :
|
||||
LawfulOrderBEq α where
|
||||
beq_iff_le_and_ge := by
|
||||
@@ -105,7 +105,7 @@ public instance LawfulOrderBEq.of_ord (α : Type u) [Ord α] [BEq α] [LE α] [L
|
||||
/--
|
||||
This lemma derives a `LawfulOrderInf α` instance from a property involving an `Ord α` instance.
|
||||
-/
|
||||
public instance LawfulOrderInf.of_ord (α : Type u) [Ord α] [Min α] [LE α] [LawfulOrderOrd α]
|
||||
public theorem LawfulOrderInf.of_ord (α : Type u) [Ord α] [Min α] [LE α] [LawfulOrderOrd α]
|
||||
(compare_min_isLE_iff : ∀ a b c : α,
|
||||
(compare a (min b c)).isLE ↔ (compare a b).isLE ∧ (compare a c).isLE) :
|
||||
LawfulOrderInf α where
|
||||
@@ -114,7 +114,7 @@ public instance LawfulOrderInf.of_ord (α : Type u) [Ord α] [Min α] [LE α] [L
|
||||
/--
|
||||
This lemma derives a `LawfulOrderMin α` instance from a property involving an `Ord α` instance.
|
||||
-/
|
||||
public instance LawfulOrderMin.of_ord (α : Type u) [Ord α] [Min α] [LE α] [LawfulOrderOrd α]
|
||||
public theorem LawfulOrderMin.of_ord (α : Type u) [Ord α] [Min α] [LE α] [LawfulOrderOrd α]
|
||||
(compare_min_isLE_iff : ∀ a b c : α,
|
||||
(compare a (min b c)).isLE ↔ (compare a b).isLE ∧ (compare a c).isLE)
|
||||
(min_eq_or : ∀ a b : α, min a b = a ∨ min a b = b) :
|
||||
@@ -125,7 +125,7 @@ public instance LawfulOrderMin.of_ord (α : Type u) [Ord α] [Min α] [LE α] [L
|
||||
/--
|
||||
This lemma derives a `LawfulOrderSup α` instance from a property involving an `Ord α` instance.
|
||||
-/
|
||||
public instance LawfulOrderSup.of_ord (α : Type u) [Ord α] [Max α] [LE α] [LawfulOrderOrd α]
|
||||
public theorem LawfulOrderSup.of_ord (α : Type u) [Ord α] [Max α] [LE α] [LawfulOrderOrd α]
|
||||
(compare_max_isLE_iff : ∀ a b c : α,
|
||||
(compare (max a b) c).isLE ↔ (compare a c).isLE ∧ (compare b c).isLE) :
|
||||
LawfulOrderSup α where
|
||||
@@ -134,7 +134,7 @@ public instance LawfulOrderSup.of_ord (α : Type u) [Ord α] [Max α] [LE α] [L
|
||||
/--
|
||||
This lemma derives a `LawfulOrderMax α` instance from a property involving an `Ord α` instance.
|
||||
-/
|
||||
public instance LawfulOrderMax.of_ord (α : Type u) [Ord α] [Max α] [LE α] [LawfulOrderOrd α]
|
||||
public theorem LawfulOrderMax.of_ord (α : Type u) [Ord α] [Max α] [LE α] [LawfulOrderOrd α]
|
||||
(compare_max_isLE_iff : ∀ a b c : α,
|
||||
(compare (max a b) c).isLE ↔ (compare a c).isLE ∧ (compare b c).isLE)
|
||||
(max_eq_or : ∀ a b : α, max a b = a ∨ max a b = b) :
|
||||
|
||||
@@ -32,24 +32,26 @@ partial def Loop.forIn {β : Type u} {m : Type u → Type v} [Monad m] (_ : Loop
|
||||
instance [Monad m] : ForIn m Loop Unit where
|
||||
forIn := Loop.forIn
|
||||
|
||||
syntax "repeat " doSeq : doElem
|
||||
syntax (name := doRepeat) "repeat " doSeq : doElem
|
||||
|
||||
macro_rules
|
||||
| `(doElem| repeat $seq) => `(doElem| for _ in Loop.mk do $seq)
|
||||
| `(doElem| repeat%$tk $seq) => `(doElem| for%$tk _ in Loop.mk do $seq)
|
||||
|
||||
syntax "while " ident " : " termBeforeDo " do " doSeq : doElem
|
||||
|
||||
macro_rules
|
||||
| `(doElem| while $h : $cond do $seq) => `(doElem| repeat if $h:ident : $cond then $seq else break)
|
||||
| `(doElem| while%$tk $h : $cond do $seq) =>
|
||||
`(doElem| repeat%$tk if $h:ident : $cond then $seq else break)
|
||||
|
||||
syntax "while " termBeforeDo " do " doSeq : doElem
|
||||
|
||||
macro_rules
|
||||
| `(doElem| while $cond do $seq) => `(doElem| repeat if $cond then $seq else break)
|
||||
| `(doElem| while%$tk $cond do $seq) => `(doElem| repeat%$tk if $cond then $seq else break)
|
||||
|
||||
syntax "repeat " doSeq ppDedent(ppLine) "until " term : doElem
|
||||
|
||||
macro_rules
|
||||
| `(doElem| repeat $seq until $cond) => `(doElem| repeat do $seq:doSeq; if $cond then break)
|
||||
| `(doElem| repeat%$tk $seq until $cond) =>
|
||||
`(doElem| repeat%$tk do $seq:doSeq; if $cond then break)
|
||||
|
||||
end Lean
|
||||
|
||||
@@ -90,6 +90,22 @@ partial def eraseProjIncFor (nFields : Nat) (targetId : FVarId) (ds : Array (Cod
|
||||
| break
|
||||
if !(w == z && targetId == x) then
|
||||
break
|
||||
if mask[i]!.isSome then
|
||||
/-
|
||||
Suppose we encounter a situation like
|
||||
```
|
||||
let x.1 := proj[0] y
|
||||
inc x.1
|
||||
let x.2 := proj[0] y
|
||||
inc x.2
|
||||
```
|
||||
The `inc x.2` will already have been removed. If we don't perform this check we will also
|
||||
remove `inc x.1` and have effectively removed two refcounts while only one was legal.
|
||||
-/
|
||||
keep := keep.push d
|
||||
keep := keep.push d'
|
||||
ds := ds.pop.pop
|
||||
continue
|
||||
/-
|
||||
Found
|
||||
```
|
||||
|
||||
@@ -15,3 +15,4 @@ public import Lean.Elab.BuiltinDo.Jump
|
||||
public import Lean.Elab.BuiltinDo.Misc
|
||||
public import Lean.Elab.BuiltinDo.For
|
||||
public import Lean.Elab.BuiltinDo.TryCatch
|
||||
public import Lean.Elab.BuiltinDo.Repeat
|
||||
|
||||
@@ -21,7 +21,8 @@ def elabDoIdDecl (x : Ident) (xType? : Option Term) (rhs : TSyntax `doElem) (k :
|
||||
let xType ← Term.elabType (xType?.getD (mkHole x))
|
||||
let lctx ← getLCtx
|
||||
let ctx ← read
|
||||
elabDoElem rhs <| .mk (kind := kind) x.getId xType do
|
||||
let ref ← getRef -- store the surrounding reference for error messages in `k`
|
||||
elabDoElem rhs <| .mk (kind := kind) x.getId xType do withRef ref do
|
||||
withLCtxKeepingMutVarDefs lctx ctx x.getId do
|
||||
Term.addLocalVarInfo x (← getFVarFromUserName x.getId)
|
||||
k
|
||||
|
||||
@@ -23,7 +23,7 @@ open Lean.Meta
|
||||
| `(doFor| for $[$_ : ]? $_:ident in $_ do $_) =>
|
||||
-- This is the target form of the expander, handled by `elabDoFor` below.
|
||||
Macro.throwUnsupported
|
||||
| `(doFor| for $decls:doForDecl,* do $body) =>
|
||||
| `(doFor| for%$tk $decls:doForDecl,* do $body) =>
|
||||
let decls := decls.getElems
|
||||
let `(doForDecl| $[$h? : ]? $pattern in $xs) := decls[0]! | Macro.throwUnsupported
|
||||
let mut doElems := #[]
|
||||
@@ -74,12 +74,13 @@ open Lean.Meta
|
||||
| some ($y, s') =>
|
||||
$s:ident := s'
|
||||
do $body)
|
||||
doElems := doElems.push (← `(doSeqItem| for $[$h? : ]? $x:ident in $xs do $body))
|
||||
doElems := doElems.push (← `(doSeqItem| for%$tk $[$h? : ]? $x:ident in $xs do $body))
|
||||
`(doElem| do $doElems*)
|
||||
| _ => Macro.throwUnsupported
|
||||
|
||||
@[builtin_doElem_elab Lean.Parser.Term.doFor] def elabDoFor : DoElab := fun stx dec => do
|
||||
let `(doFor| for $[$h? : ]? $x:ident in $xs do $body) := stx | throwUnsupportedSyntax
|
||||
let `(doFor| for%$tk $[$h? : ]? $x:ident in $xs do $body) := stx | throwUnsupportedSyntax
|
||||
let dec ← dec.ensureUnitAt tk
|
||||
checkMutVarsForShadowing #[x]
|
||||
let uα ← mkFreshLevelMVar
|
||||
let uρ ← mkFreshLevelMVar
|
||||
@@ -124,9 +125,6 @@ open Lean.Meta
|
||||
defs := defs.push (mkConst ``Unit.unit)
|
||||
return defs
|
||||
|
||||
unless ← isDefEq dec.resultType (← mkPUnit) do
|
||||
logError m!"Type mismatch. `for` loops have result type {← mkPUnit}, but the rest of the `do` sequence expected {dec.resultType}."
|
||||
|
||||
let (preS, σ) ← mkProdMkN (← useLoopMutVars none) mi.u
|
||||
|
||||
let (app, p?) ← match h? with
|
||||
|
||||
@@ -17,6 +17,7 @@ namespace Lean.Elab.Do
|
||||
open Lean.Parser.Term
|
||||
open Lean.Meta
|
||||
|
||||
open InternalSyntax in
|
||||
/--
|
||||
If the given syntax is a `doIf`, return an equivalent `doIf` that has an `else` but no `else if`s or
|
||||
`if let`s.
|
||||
@@ -25,8 +26,8 @@ If the given syntax is a `doIf`, return an equivalent `doIf` that has an `else`
|
||||
match stx with
|
||||
| `(doElem|if $_:doIfProp then $_ else $_) =>
|
||||
Macro.throwUnsupported
|
||||
| `(doElem|if $cond:doIfCond then $t $[else if $conds:doIfCond then $ts]* $[else $e?]?) => do
|
||||
let mut e : Syntax ← e?.getDM `(doSeq|pure PUnit.unit)
|
||||
| `(doElem|if%$tk $cond:doIfCond then $t $[else if%$tks $conds:doIfCond then $ts]* $[else $e?]?) => do
|
||||
let mut e : Syntax ← e?.getDM `(doSeq| skip%$tk)
|
||||
let mut eIsSeq := true
|
||||
for (cond, t) in Array.zip (conds.reverse.push cond) (ts.reverse.push t) do
|
||||
e ← if eIsSeq then pure e else `(doSeq|$(⟨e⟩):doElem)
|
||||
|
||||
@@ -88,17 +88,18 @@ private def checkLetConfigInDo (config : Term.LetConfig) : DoElabM Unit := do
|
||||
throwError "`+generalize` is not supported in `do` blocks"
|
||||
|
||||
partial def elabDoLetOrReassign (config : Term.LetConfig) (letOrReassign : LetOrReassign) (decl : TSyntax ``letDecl)
|
||||
(dec : DoElemCont) : DoElabM Expr := do
|
||||
(tk : Syntax) (dec : DoElemCont) : DoElabM Expr := do
|
||||
checkLetConfigInDo config
|
||||
let vars ← getLetDeclVars decl
|
||||
letOrReassign.checkMutVars vars
|
||||
let dec ← dec.ensureUnitAt tk
|
||||
-- Some decl preprocessing on the patterns and expected types:
|
||||
let decl ← pushTypeIntoReassignment letOrReassign decl
|
||||
let mγ ← mkMonadicType (← read).doBlockResultType
|
||||
match decl with
|
||||
| `(letDecl| $decl:letEqnsDecl) =>
|
||||
let declNew ← `(letDecl| $(⟨← liftMacroM <| Term.expandLetEqnsDecl decl⟩):letIdDecl)
|
||||
return ← Term.withMacroExpansion decl declNew <| elabDoLetOrReassign config letOrReassign declNew dec
|
||||
return ← Term.withMacroExpansion decl declNew <| elabDoLetOrReassign config letOrReassign declNew tk dec
|
||||
| `(letDecl| $pattern:term $[: $xType?]? := $rhs) =>
|
||||
let rhs ← match xType? with | some xType => `(($rhs : $xType)) | none => pure rhs
|
||||
let contElab : DoElabM Expr := elabWithReassignments letOrReassign vars dec.continueWithUnit
|
||||
@@ -162,10 +163,11 @@ partial def elabDoLetOrReassign (config : Term.LetConfig) (letOrReassign : LetOr
|
||||
mkLetFVars #[x, h'] body (usedLetOnly := config.usedOnly) (generalizeNondepLet := false)
|
||||
| _ => throwUnsupportedSyntax
|
||||
|
||||
def elabDoArrow (letOrReassign : LetOrReassign) (stx : TSyntax [``doIdDecl, ``doPatDecl]) (dec : DoElemCont) : DoElabM Expr := do
|
||||
def elabDoArrow (letOrReassign : LetOrReassign) (stx : TSyntax [``doIdDecl, ``doPatDecl]) (tk : Syntax) (dec : DoElemCont) : DoElabM Expr := do
|
||||
match stx with
|
||||
| `(doIdDecl| $x:ident $[: $xType?]? ← $rhs) =>
|
||||
letOrReassign.checkMutVars #[x]
|
||||
let dec ← dec.ensureUnitAt tk
|
||||
-- For plain variable reassignment, we know the expected type of the reassigned variable and
|
||||
-- propagate it eagerly via type ascription if the user hasn't provided one themselves:
|
||||
let xType? ← match letOrReassign, xType? with
|
||||
@@ -177,6 +179,7 @@ def elabDoArrow (letOrReassign : LetOrReassign) (stx : TSyntax [``doIdDecl, ``do
|
||||
(kind := dec.kind)
|
||||
| `(doPatDecl| _%$pattern $[: $patType?]? ← $rhs) =>
|
||||
let x := mkIdentFrom pattern (← mkFreshUserName `__x)
|
||||
let dec ← dec.ensureUnitAt tk
|
||||
elabDoIdDecl x patType? rhs dec.continueWithUnit (kind := dec.kind)
|
||||
| `(doPatDecl| $pattern:term $[: $patType?]? ← $rhs $[| $otherwise? $(rest?)?]?) =>
|
||||
let rest? := rest?.join
|
||||
@@ -205,17 +208,18 @@ private def getLetConfigAndCheckMut (letConfigStx : TSyntax ``Parser.Term.letCon
|
||||
Term.mkLetConfig letConfigStx initConfig
|
||||
|
||||
@[builtin_doElem_elab Lean.Parser.Term.doLet] def elabDoLet : DoElab := fun stx dec => do
|
||||
let `(doLet| let $[mut%$mutTk?]? $config:letConfig $decl:letDecl) := stx | throwUnsupportedSyntax
|
||||
let `(doLet| let%$tk $[mut%$mutTk?]? $config:letConfig $decl:letDecl) := stx | throwUnsupportedSyntax
|
||||
let config ← getLetConfigAndCheckMut config mutTk?
|
||||
elabDoLetOrReassign config (.let mutTk?) decl dec
|
||||
elabDoLetOrReassign config (.let mutTk?) decl tk dec
|
||||
|
||||
@[builtin_doElem_elab Lean.Parser.Term.doHave] def elabDoHave : DoElab := fun stx dec => do
|
||||
let `(doHave| have $config:letConfig $decl:letDecl) := stx | throwUnsupportedSyntax
|
||||
let `(doHave| have%$tk $config:letConfig $decl:letDecl) := stx | throwUnsupportedSyntax
|
||||
let config ← Term.mkLetConfig config { nondep := true }
|
||||
elabDoLetOrReassign config .have decl dec
|
||||
elabDoLetOrReassign config .have decl tk dec
|
||||
|
||||
@[builtin_doElem_elab Lean.Parser.Term.doLetRec] def elabDoLetRec : DoElab := fun stx dec => do
|
||||
let `(doLetRec| let rec $decls:letRecDecls) := stx | throwUnsupportedSyntax
|
||||
let `(doLetRec| let%$tk rec $decls:letRecDecls) := stx | throwUnsupportedSyntax
|
||||
let dec ← dec.ensureUnitAt tk
|
||||
let vars ← getLetRecDeclsVars decls
|
||||
let mγ ← mkMonadicType (← read).doBlockResultType
|
||||
doElabToSyntax m!"let rec body of group {vars}" dec.continueWithUnit fun body => do
|
||||
@@ -227,13 +231,13 @@ private def getLetConfigAndCheckMut (letConfigStx : TSyntax ``Parser.Term.letCon
|
||||
@[builtin_doElem_elab Lean.Parser.Term.doReassign] def elabDoReassign : DoElab := fun stx dec => do
|
||||
-- def doReassign := letIdDeclNoBinders <|> letPatDecl
|
||||
match stx with
|
||||
| `(doReassign| $x:ident $[: $xType?]? := $rhs) =>
|
||||
| `(doReassign| $x:ident $[: $xType?]? :=%$tk $rhs) =>
|
||||
let decl : TSyntax ``letIdDecl ← `(letIdDecl| $x:ident $[: $xType?]? := $rhs)
|
||||
let decl : TSyntax ``letDecl := ⟨mkNode ``letDecl #[decl]⟩
|
||||
elabDoLetOrReassign {} .reassign decl dec
|
||||
elabDoLetOrReassign {} .reassign decl tk dec
|
||||
| `(doReassign| $decl:letPatDecl) =>
|
||||
let decl : TSyntax ``letDecl := ⟨mkNode ``letDecl #[decl]⟩
|
||||
elabDoLetOrReassign {} .reassign decl dec
|
||||
elabDoLetOrReassign {} .reassign decl decl dec
|
||||
| _ => throwUnsupportedSyntax
|
||||
|
||||
@[builtin_doElem_elab Lean.Parser.Term.doLetElse] def elabDoLetElse : DoElab := fun stx dec => do
|
||||
@@ -255,17 +259,17 @@ private def getLetConfigAndCheckMut (letConfigStx : TSyntax ``Parser.Term.letCon
|
||||
elabDoElem (← `(doElem| match $rhs:term with | $pattern => $body:doSeqIndent | _ => $otherwise:doSeqIndent)) dec
|
||||
|
||||
@[builtin_doElem_elab Lean.Parser.Term.doLetArrow] def elabDoLetArrow : DoElab := fun stx dec => do
|
||||
let `(doLetArrow| let $[mut%$mutTk?]? $cfg:letConfig $decl) := stx | throwUnsupportedSyntax
|
||||
let `(doLetArrow| let%$tk $[mut%$mutTk?]? $cfg:letConfig $decl) := stx | throwUnsupportedSyntax
|
||||
let config ← getLetConfigAndCheckMut cfg mutTk?
|
||||
checkLetConfigInDo config
|
||||
if config.nondep || config.usedOnly || config.zeta || config.eq?.isSome then
|
||||
throwErrorAt cfg "configuration options are not supported with `←`"
|
||||
elabDoArrow (.let mutTk?) decl dec
|
||||
elabDoArrow (.let mutTk?) decl tk dec
|
||||
|
||||
@[builtin_doElem_elab Lean.Parser.Term.doReassignArrow] def elabDoReassignArrow : DoElab := fun stx dec => do
|
||||
match stx with
|
||||
| `(doReassignArrow| $decl:doIdDecl) =>
|
||||
elabDoArrow .reassign decl dec
|
||||
elabDoArrow .reassign decl decl dec
|
||||
| `(doReassignArrow| $decl:doPatDecl) =>
|
||||
elabDoArrow .reassign decl dec
|
||||
elabDoArrow .reassign decl decl dec
|
||||
| _ => throwUnsupportedSyntax
|
||||
|
||||
@@ -16,6 +16,12 @@ namespace Lean.Elab.Do
|
||||
open Lean.Parser.Term
|
||||
open Lean.Meta
|
||||
|
||||
open InternalSyntax in
|
||||
@[builtin_doElem_elab Lean.Parser.Term.InternalSyntax.doSkip] def elabDoSkip : DoElab := fun stx dec => do
|
||||
let `(doSkip| skip%$tk) := stx | throwUnsupportedSyntax
|
||||
let dec ← dec.ensureUnitAt tk
|
||||
dec.continueWithUnit
|
||||
|
||||
@[builtin_doElem_elab Lean.Parser.Term.doExpr] def elabDoExpr : DoElab := fun stx dec => do
|
||||
let `(doExpr| $e:term) := stx | throwUnsupportedSyntax
|
||||
let mα ← mkMonadicType dec.resultType
|
||||
@@ -26,24 +32,28 @@ open Lean.Meta
|
||||
let `(doNested| do $doSeq) := stx | throwUnsupportedSyntax
|
||||
elabDoSeq ⟨doSeq.raw⟩ dec
|
||||
|
||||
open InternalSyntax in
|
||||
@[builtin_doElem_elab Lean.Parser.Term.doUnless] def elabDoUnless : DoElab := fun stx dec => do
|
||||
let `(doUnless| unless $cond do $body) := stx | throwUnsupportedSyntax
|
||||
elabDoElem (← `(doElem| if $cond then pure PUnit.unit else $body)) dec
|
||||
let `(doUnless| unless%$tk $cond do $body) := stx | throwUnsupportedSyntax
|
||||
elabDoElem (← `(doElem| if $cond then skip%$tk else $body)) dec
|
||||
|
||||
@[builtin_doElem_elab Lean.Parser.Term.doDbgTrace] def elabDoDbgTrace : DoElab := fun stx dec => do
|
||||
let `(doDbgTrace| dbg_trace $msg:term) := stx | throwUnsupportedSyntax
|
||||
let `(doDbgTrace| dbg_trace%$tk $msg:term) := stx | throwUnsupportedSyntax
|
||||
let mγ ← mkMonadicType (← read).doBlockResultType
|
||||
let dec ← dec.ensureUnitAt tk
|
||||
doElabToSyntax "dbg_trace body" dec.continueWithUnit fun body => do
|
||||
Term.elabTerm (← `(dbg_trace $msg; $body)) mγ
|
||||
|
||||
@[builtin_doElem_elab Lean.Parser.Term.doAssert] def elabDoAssert : DoElab := fun stx dec => do
|
||||
let `(doAssert| assert! $cond) := stx | throwUnsupportedSyntax
|
||||
let `(doAssert| assert!%$tk $cond) := stx | throwUnsupportedSyntax
|
||||
let mγ ← mkMonadicType (← read).doBlockResultType
|
||||
let dec ← dec.ensureUnitAt tk
|
||||
doElabToSyntax "assert! body" dec.continueWithUnit fun body => do
|
||||
Term.elabTerm (← `(assert! $cond; $body)) mγ
|
||||
|
||||
@[builtin_doElem_elab Lean.Parser.Term.doDebugAssert] def elabDoDebugAssert : DoElab := fun stx dec => do
|
||||
let `(doDebugAssert| debug_assert! $cond) := stx | throwUnsupportedSyntax
|
||||
let `(doDebugAssert| debug_assert!%$tk $cond) := stx | throwUnsupportedSyntax
|
||||
let mγ ← mkMonadicType (← read).doBlockResultType
|
||||
let dec ← dec.ensureUnitAt tk
|
||||
doElabToSyntax "debug_assert! body" dec.continueWithUnit fun body => do
|
||||
Term.elabTerm (← `(debug_assert! $cond; $body)) mγ
|
||||
|
||||
33
src/Lean/Elab/BuiltinDo/Repeat.lean
Normal file
33
src/Lean/Elab/BuiltinDo/Repeat.lean
Normal file
@@ -0,0 +1,33 @@
|
||||
/-
|
||||
Copyright (c) 2026 Lean FRO, LLC. All rights reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
Authors: Sebastian Graf
|
||||
-/
|
||||
module
|
||||
|
||||
prelude
|
||||
public import Lean.Elab.BuiltinDo.Basic
|
||||
meta import Lean.Parser.Do
|
||||
import Lean.Elab.BuiltinDo.For
|
||||
|
||||
public section
|
||||
|
||||
namespace Lean.Elab.Do
|
||||
|
||||
open Lean.Parser.Term
|
||||
|
||||
/--
|
||||
Builtin do-element elaborator for `repeat` (syntax kind `Lean.doRepeat`).
|
||||
|
||||
Expands to `for _ in Loop.mk do ...`. A follow-up PR will drop the fallback macro
|
||||
in `Init.While` (which currently preempts this elaborator) and extend this
|
||||
elaborator to choose between `Loop.mk` and a well-founded `Repeat.mk` based on a
|
||||
configuration option.
|
||||
-/
|
||||
@[builtin_doElem_elab Lean.doRepeat] def elabDoRepeat : DoElab := fun stx dec => do
|
||||
let `(doElem| repeat $seq) := stx | throwUnsupportedSyntax
|
||||
let expanded ← `(doElem| for _ in Loop.mk do $seq)
|
||||
Term.withMacroExpansion stx expanded <|
|
||||
withRef expanded <| elabDoElem ⟨expanded⟩ dec
|
||||
|
||||
end Lean.Elab.Do
|
||||
@@ -220,7 +220,7 @@ def processDefDeriving (view : DerivingClassView) (decl : Expr) (isNoncomputable
|
||||
instName ← liftMacroM <| mkUnusedBaseName instName
|
||||
if isPrivateName declName then
|
||||
instName := mkPrivateName env instName
|
||||
let isMeta := (← read).declName?.any (isMarkedMeta (← getEnv))
|
||||
let isMeta := (← read).isMetaSection || isMarkedMeta (← getEnv) declName
|
||||
let inst ← if backward.inferInstanceAs.wrap.get (← getOptions) then
|
||||
withDeclNameForAuxNaming instName <| withNewMCtxDepth <|
|
||||
wrapInstance result.instVal result.instType
|
||||
@@ -255,11 +255,12 @@ def processDefDeriving (view : DerivingClassView) (decl : Expr) (isNoncomputable
|
||||
logInfoAt cmdRef m!"Try this: {newText}"
|
||||
throwError "failed to derive instance because it depends on \
|
||||
`{.ofConstName noncompRef}`, which is noncomputable"
|
||||
let isMeta := (← read).isMetaSection || isMarkedMeta (← getEnv) declName
|
||||
if isNoncomputable || (← read).isNoncomputableSection then
|
||||
addDecl <| Declaration.defnDecl decl
|
||||
modifyEnv (addNoncomputable · instName)
|
||||
else
|
||||
addAndCompile <| Declaration.defnDecl decl
|
||||
addAndCompile (Declaration.defnDecl decl) (markMeta := isMeta)
|
||||
trace[Elab.Deriving] "Derived instance `{.ofConstName instName}`"
|
||||
-- For Prop-typed instances (theorems), skip `implicit_reducible` since reducibility hints are
|
||||
-- irrelevant for theorems. This matches the behavior of the handwritten `instance` command
|
||||
|
||||
@@ -374,14 +374,60 @@ def withLCtxKeepingMutVarDefs (oldLCtx : LocalContext) (oldCtx : Context) (resul
|
||||
mutVarDefs := oldMutVarDefs
|
||||
}) k
|
||||
|
||||
def mkMonadicResultTypeMismatchError (contType : Expr) (elementType : Expr) : MessageData :=
|
||||
m!"Type mismatch. The `do` element has monadic result type{indentExpr elementType}\n\
|
||||
but the rest of the `do` block has monadic result type{indentExpr contType}"
|
||||
|
||||
/--
|
||||
Given a continuation `dec`, a reference `ref`, and an element result type `elementType`, returns a
|
||||
continuation derived from `dec` with result type `elementType`.
|
||||
If `dec` already has result type `elementType`, simply returns `dec`.
|
||||
Otherwise, an error is logged and a new continuation is returned that calls `dec` with `sorry` as a
|
||||
result. The error is reported at `ref`.
|
||||
-/
|
||||
def DoElemCont.ensureHasTypeAt (dec : DoElemCont) (ref : Syntax) (elementType : Expr) : DoElabM DoElemCont := do
|
||||
if ← isDefEqGuarded dec.resultType elementType then
|
||||
return dec
|
||||
let errMessage := mkMonadicResultTypeMismatchError dec.resultType elementType
|
||||
unless (← readThe Term.Context).errToSorry do
|
||||
throwErrorAt ref errMessage
|
||||
logErrorAt ref errMessage
|
||||
return {
|
||||
resultName := ← mkFreshUserName `__r
|
||||
resultType := elementType
|
||||
k := do
|
||||
mapLetDecl dec.resultName dec.resultType (← mkSorry dec.resultType true)
|
||||
(nondep := true) (kind := .implDetail) fun _ => dec.k
|
||||
kind := dec.kind
|
||||
}
|
||||
|
||||
/--
|
||||
Given a continuation `dec` and a reference `ref`, returns a continuation derived from `dec` with result type `PUnit`.
|
||||
If `dec` already has result type `PUnit`, simply returns `dec`. Otherwise, an error is logged and a
|
||||
new continuation is returned that calls `dec` with `sorry` as a result. The error is reported at `ref`.
|
||||
-/
|
||||
def DoElemCont.ensureUnitAt (dec : DoElemCont) (ref : Syntax) : DoElabM DoElemCont := do
|
||||
dec.ensureHasTypeAt ref (← mkPUnit)
|
||||
|
||||
/--
|
||||
Given a continuation `dec`, returns a continuation derived from `dec` with result type `PUnit`.
|
||||
If `dec` already has result type `PUnit`, simply returns `dec`. Otherwise, an error is logged and a
|
||||
new continuation is returned that calls `dec` with `sorry` as a result.
|
||||
-/
|
||||
def DoElemCont.ensureUnit (dec : DoElemCont) : DoElabM DoElemCont := do
|
||||
dec.ensureUnitAt (← getRef)
|
||||
|
||||
/--
|
||||
Return `$e >>= fun ($dec.resultName : $dec.resultType) => $(← dec.k)`, cancelling
|
||||
the bind if `$(← dec.k)` is `pure $dec.resultName` or `e` is some `pure` computation.
|
||||
-/
|
||||
def DoElemCont.mkBindUnlessPure (dec : DoElemCont) (e : Expr) : DoElabM Expr := do
|
||||
-- let eResultTy ← mkFreshResultType
|
||||
-- let e ← Term.ensureHasType (← mkMonadicType eResultTy) e
|
||||
-- let dec ← dec.ensureHasType eResultTy
|
||||
let x := dec.resultName
|
||||
let eResultTy := dec.resultType
|
||||
let k := dec.k
|
||||
let eResultTy := dec.resultType
|
||||
-- The .ofBinderName below is mainly to interpret `__do_lift` binders as implementation details.
|
||||
let declKind := .ofBinderName x
|
||||
let kResultTy ← mkFreshResultType `kResultTy
|
||||
@@ -421,9 +467,8 @@ Return `let $k.resultName : PUnit := PUnit.unit; $(← k.k)`, ensuring that the
|
||||
is `PUnit` and then immediately zeta-reduce the `let`.
|
||||
-/
|
||||
def DoElemCont.continueWithUnit (dec : DoElemCont) : DoElabM Expr := do
|
||||
let unit ← mkPUnitUnit
|
||||
discard <| Term.ensureHasType dec.resultType unit
|
||||
mapLetDeclZeta dec.resultName (← mkPUnit) unit (nondep := true) (kind := .ofBinderName dec.resultName) fun _ =>
|
||||
let dec ← dec.ensureUnit
|
||||
mapLetDeclZeta dec.resultName (← mkPUnit) (← mkPUnitUnit) (nondep := true) (kind := .ofBinderName dec.resultName) fun _ =>
|
||||
dec.k
|
||||
|
||||
/-- Elaborate the `DoElemCont` with the `deadCode` flag set to `deadSyntactically` to emit warnings. -/
|
||||
@@ -604,6 +649,7 @@ def enterFinally (resultType : Expr) (k : DoElabM Expr) : DoElabM Expr := do
|
||||
/-- Extracts `MonadInfo` and monadic result type `α` from the expected type of a `do` block `m α`. -/
|
||||
private partial def extractMonadInfo (expectedType? : Option Expr) : Term.TermElabM (MonadInfo × Expr) := do
|
||||
let some expectedType := expectedType? | mkUnknownMonadResult
|
||||
let expectedType ← instantiateMVars expectedType
|
||||
let extractStep? (type : Expr) : Term.TermElabM (Option (MonadInfo × Expr)) := do
|
||||
let .app m resultType := type.consumeMData | return none
|
||||
unless ← isType resultType do return none
|
||||
|
||||
@@ -79,6 +79,7 @@ builtin_initialize controlInfoElemAttribute : KeyedDeclsAttribute ControlInfoHan
|
||||
|
||||
namespace InferControlInfo
|
||||
|
||||
open InternalSyntax in
|
||||
mutual
|
||||
|
||||
partial def ofElem (stx : TSyntax `doElem) : TermElabM ControlInfo := do
|
||||
@@ -152,6 +153,7 @@ partial def ofElem (stx : TSyntax `doElem) : TermElabM ControlInfo := do
|
||||
let finInfo ← ofOptionSeq finSeq?
|
||||
return info.sequence finInfo
|
||||
-- Misc
|
||||
| `(doElem| skip) => return .pure
|
||||
| `(doElem| dbg_trace $_) => return .pure
|
||||
| `(doElem| assert! $_) => return .pure
|
||||
| `(doElem| debug_assert! $_) => return .pure
|
||||
|
||||
@@ -1782,6 +1782,10 @@ mutual
|
||||
doIfToCode doElem doElems
|
||||
else if k == ``Parser.Term.doUnless then
|
||||
doUnlessToCode doElem doElems
|
||||
else if k == `Lean.doRepeat then
|
||||
let seq := doElem[1]
|
||||
let expanded ← `(doElem| for _ in Loop.mk do $seq)
|
||||
doSeqToCode (expanded :: doElems)
|
||||
else if k == ``Parser.Term.doFor then withFreshMacroScope do
|
||||
doForToCode doElem doElems
|
||||
else if k == ``Parser.Term.doMatch then
|
||||
@@ -1815,6 +1819,13 @@ mutual
|
||||
return mkTerminalAction term
|
||||
else
|
||||
return mkSeq term (← doSeqToCode doElems)
|
||||
else if k == ``Parser.Term.InternalSyntax.doSkip then
|
||||
-- In the legacy elaborator, `skip` is treated as `pure PUnit.unit`.
|
||||
let term ← withRef doElem `(pure PUnit.unit)
|
||||
if doElems.isEmpty then
|
||||
return mkTerminalAction term
|
||||
else
|
||||
return mkSeq term (← doSeqToCode doElems)
|
||||
else
|
||||
throwError "unexpected do-element of kind {doElem.getKind}:\n{doElem}"
|
||||
end
|
||||
|
||||
@@ -364,8 +364,9 @@ def elabIdbgTerm : TermElab := fun stx expectedType? => do
|
||||
|
||||
@[builtin_doElem_elab Lean.Parser.Term.doIdbg]
|
||||
def elabDoIdbg : DoElab := fun stx dec => do
|
||||
let `(Lean.Parser.Term.doIdbg| idbg $e) := stx | throwUnsupportedSyntax
|
||||
let `(Lean.Parser.Term.doIdbg| idbg%$tk $e) := stx | throwUnsupportedSyntax
|
||||
let mγ ← mkMonadicType (← read).doBlockResultType
|
||||
let dec ← dec.ensureUnitAt tk
|
||||
doElabToSyntax "idbg body" dec.continueWithUnit fun body => do
|
||||
elabIdbgCore (e := e) (body := body) (ref := stx) mγ
|
||||
|
||||
|
||||
@@ -73,6 +73,8 @@ private def inductiveSyntaxToView (modifiers : Modifiers) (decl : Syntax) (isCoi
|
||||
throwError "Constructor cannot be `protected` because it is in a `private` inductive datatype"
|
||||
checkValidCtorModifier ctorModifiers
|
||||
let ctorName := ctor.getIdAt 3
|
||||
if ctorName.hasMacroScopes && isCoinductive then
|
||||
throwError "Coinductive predicates are not allowed inside of macro scopes"
|
||||
let ctorName := declName ++ ctorName
|
||||
let ctorName ← withRef ctor[3] <| applyVisibility ctorModifiers ctorName
|
||||
let (binders, type?) := expandOptDeclSig ctor[4]
|
||||
|
||||
@@ -69,12 +69,16 @@ def decLevel (u : Level) : MetaM Level := do
|
||||
|
||||
/-- This method is useful for inferring universe level parameters for function that take arguments such as `{α : Type u}`.
|
||||
Recall that `Type u` is `Sort (u+1)` in Lean. Thus, given `α`, we must infer its universe level,
|
||||
and then decrement 1 to obtain `u`. -/
|
||||
instantiate and normalize it, and then decrement 1 to obtain `u`. -/
|
||||
def getDecLevel (type : Expr) : MetaM Level := do
|
||||
decLevel (← getLevel type)
|
||||
let l ← getLevel type
|
||||
let l ← normalizeLevel l
|
||||
decLevel l
|
||||
|
||||
def getDecLevel? (type : Expr) : MetaM (Option Level) := do
|
||||
decLevel? (← getLevel type)
|
||||
let l ← getLevel type
|
||||
let l ← normalizeLevel l
|
||||
decLevel? l
|
||||
|
||||
builtin_initialize
|
||||
registerTraceClass `Meta.isLevelDefEq.step
|
||||
|
||||
@@ -229,8 +229,33 @@ private partial def computeSynthOrder (inst : Expr) (projInfo? : Option Projecti
|
||||
|
||||
return synthed
|
||||
|
||||
def checkImpossibleInstance (c : Expr) : MetaM Unit := do
|
||||
let cTy ← inferType c
|
||||
forallTelescopeReducing cTy fun args ty => do
|
||||
let argTys ← args.mapM inferType
|
||||
let impossibleArgs ← args.zipIdx.filterMapM fun (arg, i) => do
|
||||
let fv := arg.fvarId!
|
||||
if (← fv.getDecl).binderInfo.isInstImplicit then return none
|
||||
if ty.containsFVar fv then return none
|
||||
if argTys[i+1:].any (·.containsFVar fv) then return none
|
||||
return some m!"{arg} : {← inferType arg}"
|
||||
if impossibleArgs.isEmpty then return
|
||||
let impossibleArgs := MessageData.joinSep impossibleArgs.toList ", "
|
||||
throwError m!"Instance {c} has arguments "
|
||||
++ impossibleArgs
|
||||
++ " that are impossible to infer. Those arguments are not instance-implicit and do not appear in another instance-implicit argument or the return type."
|
||||
|
||||
def checkNonClassInstance (declName : Name) (c : Expr) : MetaM Unit := do
|
||||
let type ← inferType c
|
||||
forallTelescopeReducing type fun _ target => do
|
||||
unless (← isClass? target).isSome do
|
||||
unless target.isSorry do
|
||||
throwError m!"instance `{declName}` target `{target}` is not a type class."
|
||||
|
||||
def addInstance (declName : Name) (attrKind : AttributeKind) (prio : Nat) : MetaM Unit := do
|
||||
let c ← mkConstWithLevelParams declName
|
||||
checkImpossibleInstance c
|
||||
checkNonClassInstance declName c
|
||||
let keys ← mkInstanceKey c
|
||||
let status ← getReducibilityStatus declName
|
||||
unless status matches .reducible | .implicitReducible do
|
||||
|
||||
@@ -51,7 +51,7 @@ register_builtin_option debug.tactic.simp.checkDefEqAttr : Bool := {
|
||||
}
|
||||
|
||||
register_builtin_option warning.simp.varHead : Bool := {
|
||||
defValue := false
|
||||
defValue := true
|
||||
descr := "If true, warns when the head symbol of the left-hand side of a `@[simp]` theorem \
|
||||
is a variable. Such lemmas are tried on every simp step, which can be slow."
|
||||
}
|
||||
|
||||
@@ -66,6 +66,14 @@ def notFollowedByRedefinedTermToken :=
|
||||
"do" <|> "dbg_trace" <|> "idbg" <|> "assert!" <|> "debug_assert!" <|> "for" <|> "unless" <|> "return" <|> symbol "try")
|
||||
"token at 'do' element"
|
||||
|
||||
namespace InternalSyntax
|
||||
/--
|
||||
Internal syntax used in the `if` and `unless` elaborators. Behaves like `pure PUnit.unit` but
|
||||
uses `()` if possible and gives better error messages.
|
||||
-/
|
||||
scoped syntax (name := doSkip) "skip" : doElem
|
||||
end InternalSyntax
|
||||
|
||||
@[builtin_doElem_parser] def doLet := leading_parser
|
||||
"let " >> optional "mut " >> letConfig >> letDecl
|
||||
@[builtin_doElem_parser] def doLetElse := leading_parser withPosition <|
|
||||
|
||||
@@ -117,12 +117,13 @@ private partial def isSyntheticTacticCompletion
|
||||
(cmdStx : Syntax)
|
||||
: Bool := Id.run do
|
||||
let hoverFilePos := fileMap.toPosition hoverPos
|
||||
go hoverFilePos cmdStx 0
|
||||
go hoverFilePos cmdStx 0 none
|
||||
where
|
||||
go
|
||||
(hoverFilePos : Position)
|
||||
(stx : Syntax)
|
||||
(leadingWs : Nat)
|
||||
(hoverFilePos : Position)
|
||||
(stx : Syntax)
|
||||
(leadingWs : Nat)
|
||||
(leadingTokenTailPos? : Option String.Pos.Raw)
|
||||
: Bool := Id.run do
|
||||
match stx.getPos?, stx.getTailPos? with
|
||||
| some startPos, some endPos =>
|
||||
@@ -132,8 +133,9 @@ where
|
||||
if ! isCursorInCompletionRange then
|
||||
return false
|
||||
let mut wsBeforeArg := leadingWs
|
||||
let mut lastArgTailPos? := leadingTokenTailPos?
|
||||
for arg in stx.getArgs do
|
||||
if go hoverFilePos arg wsBeforeArg then
|
||||
if go hoverFilePos arg wsBeforeArg lastArgTailPos? then
|
||||
return true
|
||||
-- We must account for the whitespace before an argument because the syntax nodes we use
|
||||
-- to identify tactic blocks only start *after* the whitespace following a `by`, and we
|
||||
@@ -141,7 +143,12 @@ where
|
||||
-- This method of computing whitespace assumes that there are no syntax nodes without tokens
|
||||
-- after `by` and before the first proper tactic syntax.
|
||||
wsBeforeArg := arg.getTrailingSize
|
||||
return isCompletionInEmptyTacticBlock stx
|
||||
-- Track the tail position of the most recent preceding sibling that has a position so
|
||||
-- that empty tactic blocks (which lack positions) can locate their opening token (e.g.
|
||||
-- the `by` keyword) for indentation checking. The tail position lets us distinguish
|
||||
-- cursors before and after the opener on the opener's line.
|
||||
lastArgTailPos? := arg.getTailPos? <|> lastArgTailPos?
|
||||
return isCompletionInEmptyTacticBlock stx lastArgTailPos?
|
||||
|| isCompletionAfterSemicolon stx
|
||||
|| isCompletionOnTacticBlockIndentation hoverFilePos stx
|
||||
| _, _ =>
|
||||
@@ -150,7 +157,7 @@ where
|
||||
-- tactic blocks always occur within other syntax with ranges that let us narrow down the
|
||||
-- search to the degree that we can be sure that the cursor is indeed in this empty tactic
|
||||
-- block.
|
||||
return isCompletionInEmptyTacticBlock stx
|
||||
return isCompletionInEmptyTacticBlock stx leadingTokenTailPos?
|
||||
|
||||
isCompletionOnTacticBlockIndentation
|
||||
(hoverFilePos : Position)
|
||||
@@ -190,8 +197,47 @@ where
|
||||
else
|
||||
none
|
||||
|
||||
isCompletionInEmptyTacticBlock (stx : Syntax) : Bool :=
|
||||
isCursorInProperWhitespace fileMap hoverPos && isEmptyTacticBlock stx
|
||||
isCompletionInEmptyTacticBlock (stx : Syntax) (leadingTokenTailPos? : Option String.Pos.Raw) : Bool := Id.run do
|
||||
if ! isCursorInProperWhitespace fileMap hoverPos then
|
||||
return false
|
||||
if ! isEmptyTacticBlock stx then
|
||||
return false
|
||||
-- Bracketed tactic blocks `{ ... }` are delimited by the braces themselves, so tactics
|
||||
-- inserted in an empty bracketed block can appear at any column between the braces
|
||||
-- (`withoutPosition` disables indentation constraints inside `tacticSeqBracketed`).
|
||||
if stx.getKind == ``Parser.Tactic.tacticSeqBracketed then
|
||||
let some openEndPos := stx[0].getTailPos?
|
||||
| return false
|
||||
let some closeStartPos := stx[2].getPos?
|
||||
| return false
|
||||
return openEndPos.byteIdx <= hoverPos.byteIdx && hoverPos.byteIdx <= closeStartPos.byteIdx
|
||||
return isAtExpectedTacticIndentation leadingTokenTailPos?
|
||||
|
||||
-- After an empty tactic opener like `by`, tactics on a subsequent line must be inserted at an
|
||||
-- increased indentation level (two spaces past the indentation of the line containing the
|
||||
-- opener token). We mirror that here so that tactic completions are not offered in positions
|
||||
-- where a tactic could not actually be inserted. On the same line as the opener, completions
|
||||
-- are allowed only in the trailing whitespace past the opener — cursors earlier on the line
|
||||
-- belong to the surrounding term, not to the tactic block.
|
||||
isAtExpectedTacticIndentation (leadingTokenTailPos? : Option String.Pos.Raw) : Bool := Id.run do
|
||||
let some tokenTailPos := leadingTokenTailPos?
|
||||
| return true
|
||||
let hoverFilePos := fileMap.toPosition hoverPos
|
||||
let tokenTailFilePos := fileMap.toPosition tokenTailPos
|
||||
if hoverFilePos.line == tokenTailFilePos.line then
|
||||
return hoverPos.byteIdx >= tokenTailPos.byteIdx
|
||||
let expectedColumn := countLeadingSpaces (fileMap.lineStart tokenTailFilePos.line) + 2
|
||||
return hoverFilePos.column == expectedColumn
|
||||
|
||||
countLeadingSpaces (pos : String.Pos.Raw) : Nat := Id.run do
|
||||
let mut p := pos
|
||||
let mut n : Nat := 0
|
||||
while ! p.atEnd fileMap.source do
|
||||
if p.get fileMap.source != ' ' then
|
||||
break
|
||||
p := p.next fileMap.source
|
||||
n := n + 1
|
||||
return n
|
||||
|
||||
isEmptyTacticBlock (stx : Syntax) : Bool :=
|
||||
stx.getKind == ``Parser.Tactic.tacticSeq && isEmpty stx
|
||||
|
||||
@@ -18,7 +18,7 @@ open Std.DHashMap.Internal
|
||||
|
||||
namespace Std.DHashMap.Raw
|
||||
|
||||
instance instDecidableEquiv {α : Type u} {β : α → Type v} [BEq α] [LawfulBEq α] [Hashable α] [∀ k, BEq (β k)] [∀ k, LawfulBEq (β k)] {m₁ m₂ : Raw α β} (h₁ : m₁.WF) (h₂ : m₂.WF) : Decidable (m₁ ~m m₂) :=
|
||||
def instDecidableEquiv {α : Type u} {β : α → Type v} [BEq α] [LawfulBEq α] [Hashable α] [∀ k, BEq (β k)] [∀ k, LawfulBEq (β k)] {m₁ m₂ : Raw α β} (h₁ : m₁.WF) (h₂ : m₂.WF) : Decidable (m₁ ~m m₂) :=
|
||||
Raw₀.decidableEquiv ⟨m₁, h₁.size_buckets_pos⟩ ⟨m₂, h₂.size_buckets_pos⟩ h₁ h₂
|
||||
|
||||
end Std.DHashMap.Raw
|
||||
|
||||
@@ -19,7 +19,7 @@ open Std.DTreeMap.Internal.Impl
|
||||
|
||||
namespace Std.DTreeMap.Raw
|
||||
|
||||
instance instDecidableEquiv {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} [TransCmp cmp] [LawfulEqCmp cmp] [∀ k, BEq (β k)] [∀ k, LawfulBEq (β k)] {t₁ t₂ : Raw α β cmp} (h₁ : t₁.WF) (h₂ : t₂.WF) : Decidable (t₁ ~m t₂) :=
|
||||
def instDecidableEquiv {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} [TransCmp cmp] [LawfulEqCmp cmp] [∀ k, BEq (β k)] [∀ k, LawfulBEq (β k)] {t₁ t₂ : Raw α β cmp} (h₁ : t₁.WF) (h₂ : t₂.WF) : Decidable (t₁ ~m t₂) :=
|
||||
let : Ord α := ⟨cmp⟩;
|
||||
let : Decidable (t₁.inner ~m t₂.inner) := decidableEquiv t₁.1 t₂.1 h₁ h₂;
|
||||
decidable_of_iff _ ⟨fun h => ⟨h⟩, fun h => h.1⟩
|
||||
|
||||
@@ -19,7 +19,7 @@ open Std.DHashMap.Raw
|
||||
|
||||
namespace Std.HashMap.Raw
|
||||
|
||||
instance instDecidableEquiv {α : Type u} {β : Type v} [BEq α] [LawfulBEq α] [Hashable α] [BEq β] [LawfulBEq β] {m₁ m₂ : Raw α β} (h₁ : m₁.WF) (h₂ : m₂.WF) : Decidable (m₁ ~m m₂) :=
|
||||
def instDecidableEquiv {α : Type u} {β : Type v} [BEq α] [LawfulBEq α] [Hashable α] [BEq β] [LawfulBEq β] {m₁ m₂ : Raw α β} (h₁ : m₁.WF) (h₂ : m₂.WF) : Decidable (m₁ ~m m₂) :=
|
||||
let : Decidable (m₁.1 ~m m₂.1) := DHashMap.Raw.instDecidableEquiv h₁.out h₂.out;
|
||||
decidable_of_iff _ ⟨fun h => ⟨h⟩, fun h => h.1⟩
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ open Std.HashMap.Raw
|
||||
|
||||
namespace Std.HashSet.Raw
|
||||
|
||||
instance instDecidableEquiv {α : Type u} [BEq α] [LawfulBEq α] [Hashable α] {m₁ m₂ : Raw α} (h₁ : m₁.WF) (h₂ : m₂.WF) : Decidable (m₁ ~m m₂) :=
|
||||
def instDecidableEquiv {α : Type u} [BEq α] [LawfulBEq α] [Hashable α] {m₁ m₂ : Raw α} (h₁ : m₁.WF) (h₂ : m₂.WF) : Decidable (m₁ ~m m₂) :=
|
||||
let : Decidable (m₁.1 ~m m₂.1) := HashMap.Raw.instDecidableEquiv h₁.out h₂.out;
|
||||
decidable_of_iff _ ⟨fun h => ⟨h⟩, fun h => h.1⟩
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ open Std.DTreeMap.Raw
|
||||
|
||||
namespace Std.TreeMap.Raw
|
||||
|
||||
instance instDecidableEquiv {α : Type u} {β : Type v} {cmp : α → α → Ordering} [TransCmp cmp] [LawfulEqCmp cmp] [BEq β] [LawfulBEq β] {t₁ t₂ : Raw α β cmp} (h₁ : t₁.WF) (h₂ : t₂.WF) : Decidable (t₁ ~m t₂) :=
|
||||
def instDecidableEquiv {α : Type u} {β : Type v} {cmp : α → α → Ordering} [TransCmp cmp] [LawfulEqCmp cmp] [BEq β] [LawfulBEq β] {t₁ t₂ : Raw α β cmp} (h₁ : t₁.WF) (h₂ : t₂.WF) : Decidable (t₁ ~m t₂) :=
|
||||
let : Ord α := ⟨cmp⟩;
|
||||
let : Decidable (t₁.inner ~m t₂.inner) := DTreeMap.Raw.instDecidableEquiv h₁ h₂;
|
||||
decidable_of_iff _ ⟨fun h => ⟨h⟩, fun h => h.1⟩
|
||||
|
||||
@@ -20,7 +20,7 @@ open Std.TreeMap.Raw
|
||||
|
||||
namespace Std.TreeSet.Raw
|
||||
|
||||
instance instDecidableEquiv {α : Type u} {cmp : α → α → Ordering} [TransCmp cmp] [LawfulEqCmp cmp] {t₁ t₂ : Raw α cmp} (h₁ : t₁.WF) (h₂ : t₂.WF) : Decidable (t₁ ~m t₂) :=
|
||||
def instDecidableEquiv {α : Type u} {cmp : α → α → Ordering} [TransCmp cmp] [LawfulEqCmp cmp] {t₁ t₂ : Raw α cmp} (h₁ : t₁.WF) (h₂ : t₂.WF) : Decidable (t₁ ~m t₂) :=
|
||||
let : Ord α := ⟨cmp⟩;
|
||||
let : Decidable (t₁.inner ~m t₂.inner) := TreeMap.Raw.instDecidableEquiv h₁ h₂;
|
||||
decidable_of_iff _ ⟨fun h => ⟨h⟩, fun h => h.1⟩
|
||||
|
||||
@@ -154,6 +154,7 @@ public class FamilyOut {α : Type u} {β : Type v} (f : α → β) (a : α) (b :
|
||||
-- Simplifies proofs involving open type families.
|
||||
-- Scoped to avoid slowing down `simp` in downstream projects (the discrimination
|
||||
-- tree key is `_`, so it would be attempted on every goal).
|
||||
set_option warning.simp.varHead false in
|
||||
attribute [scoped simp] FamilyOut.fam_eq
|
||||
|
||||
public instance [FamilyDef f a b] : FamilyOut f a b where
|
||||
|
||||
@@ -752,6 +752,7 @@ extern "C" LEAN_EXPORT obj_res lean_windows_get_next_transition(b_obj_arg timezo
|
||||
u_strToUTF8(dst_name, sizeof(dst_name), &dst_name_len, tzID, tzIDLength, &status);
|
||||
|
||||
if (U_FAILURE(status)) {
|
||||
ucal_close(cal);
|
||||
return lean_io_result_mk_error(lean_mk_io_error_invalid_argument(EINVAL, mk_string("failed to convert DST name to UTF-8")));
|
||||
}
|
||||
|
||||
@@ -1397,7 +1398,7 @@ extern "C" LEAN_EXPORT obj_res lean_io_app_path() {
|
||||
memset(dest, 0, PATH_MAX);
|
||||
pid_t pid = getpid();
|
||||
snprintf(path, PATH_MAX, "/proc/%d/exe", pid);
|
||||
if (readlink(path, dest, PATH_MAX) == -1) {
|
||||
if (readlink(path, dest, PATH_MAX - 1) == -1) {
|
||||
return io_result_mk_error("failed to locate application");
|
||||
} else {
|
||||
return io_result_mk_ok(mk_string(dest));
|
||||
|
||||
@@ -54,7 +54,7 @@ ifeq "${USE_LAKE}" "ON"
|
||||
|
||||
# build in parallel
|
||||
Init:
|
||||
${PREV_STAGE}/bin/lake build -f ${CMAKE_BINARY_DIR}/lakefile.toml $(LAKE_EXTRA_ARGS)
|
||||
${PREV_STAGE}/bin/lake build -f ${CMAKE_BINARY_DIR}/lakefile.toml ${LEAN_EXTRA_LAKE_OPTS} $(LAKE_EXTRA_ARGS)
|
||||
|
||||
Std Lean Lake Leanc LeanChecker LeanIR: Init
|
||||
|
||||
|
||||
BIN
stage0/src/CMakeLists.txt
generated
BIN
stage0/src/CMakeLists.txt
generated
Binary file not shown.
BIN
stage0/src/runtime/CMakeLists.txt
generated
BIN
stage0/src/runtime/CMakeLists.txt
generated
Binary file not shown.
BIN
stage0/src/runtime/io.cpp
generated
BIN
stage0/src/runtime/io.cpp
generated
Binary file not shown.
BIN
stage0/src/stdlib.make.in
generated
BIN
stage0/src/stdlib.make.in
generated
Binary file not shown.
BIN
stage0/stdlib/Init/CbvSimproc.c
generated
BIN
stage0/stdlib/Init/CbvSimproc.c
generated
Binary file not shown.
BIN
stage0/stdlib/Init/Data/Array/QSort/Basic.c
generated
BIN
stage0/stdlib/Init/Data/Array/QSort/Basic.c
generated
Binary file not shown.
BIN
stage0/stdlib/Init/Grind/Propagator.c
generated
BIN
stage0/stdlib/Init/Grind/Propagator.c
generated
Binary file not shown.
BIN
stage0/stdlib/Init/Meta.c
generated
BIN
stage0/stdlib/Init/Meta.c
generated
Binary file not shown.
BIN
stage0/stdlib/Init/NotationExtra.c
generated
BIN
stage0/stdlib/Init/NotationExtra.c
generated
Binary file not shown.
BIN
stage0/stdlib/Init/Simproc.c
generated
BIN
stage0/stdlib/Init/Simproc.c
generated
Binary file not shown.
BIN
stage0/stdlib/Init/System/FilePath.c
generated
BIN
stage0/stdlib/Init/System/FilePath.c
generated
Binary file not shown.
BIN
stage0/stdlib/Init/System/IO.c
generated
BIN
stage0/stdlib/Init/System/IO.c
generated
Binary file not shown.
BIN
stage0/stdlib/Init/System/Uri.c
generated
BIN
stage0/stdlib/Init/System/Uri.c
generated
Binary file not shown.
BIN
stage0/stdlib/Init/Tactics.c
generated
BIN
stage0/stdlib/Init/Tactics.c
generated
Binary file not shown.
BIN
stage0/stdlib/Init/While.c
generated
BIN
stage0/stdlib/Init/While.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/Build/Actions.c
generated
BIN
stage0/stdlib/Lake/Build/Actions.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/Build/Common.c
generated
BIN
stage0/stdlib/Lake/Build/Common.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/Build/Data.c
generated
BIN
stage0/stdlib/Lake/Build/Data.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/Build/Executable.c
generated
BIN
stage0/stdlib/Lake/Build/Executable.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/Build/ExternLib.c
generated
BIN
stage0/stdlib/Lake/Build/ExternLib.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/Build/Index.c
generated
BIN
stage0/stdlib/Lake/Build/Index.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/Build/InputFile.c
generated
BIN
stage0/stdlib/Lake/Build/InputFile.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/Build/Job/Monad.c
generated
BIN
stage0/stdlib/Lake/Build/Job/Monad.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/Build/Library.c
generated
BIN
stage0/stdlib/Lake/Build/Library.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/Build/Module.c
generated
BIN
stage0/stdlib/Lake/Build/Module.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/Build/ModuleArtifacts.c
generated
BIN
stage0/stdlib/Lake/Build/ModuleArtifacts.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/Build/Package.c
generated
BIN
stage0/stdlib/Lake/Build/Package.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/Build/Run.c
generated
BIN
stage0/stdlib/Lake/Build/Run.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/Build/Store.c
generated
BIN
stage0/stdlib/Lake/Build/Store.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/CLI/Init.c
generated
BIN
stage0/stdlib/Lake/CLI/Init.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/CLI/Main.c
generated
BIN
stage0/stdlib/Lake/CLI/Main.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/CLI/Shake.c
generated
BIN
stage0/stdlib/Lake/CLI/Shake.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/CLI/Translate/Lean.c
generated
BIN
stage0/stdlib/Lake/CLI/Translate/Lean.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/CLI/Translate/Toml.c
generated
BIN
stage0/stdlib/Lake/CLI/Translate/Toml.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/Config/Artifact.c
generated
BIN
stage0/stdlib/Lake/Config/Artifact.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/Config/Cache.c
generated
BIN
stage0/stdlib/Lake/Config/Cache.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/Config/Dependency.c
generated
BIN
stage0/stdlib/Lake/Config/Dependency.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/Config/Env.c
generated
BIN
stage0/stdlib/Lake/Config/Env.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/Config/FacetConfig.c
generated
BIN
stage0/stdlib/Lake/Config/FacetConfig.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/Config/InstallPath.c
generated
BIN
stage0/stdlib/Lake/Config/InstallPath.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/Config/LeanExeConfig.c
generated
BIN
stage0/stdlib/Lake/Config/LeanExeConfig.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/Config/LeanLibConfig.c
generated
BIN
stage0/stdlib/Lake/Config/LeanLibConfig.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/Config/Meta.c
generated
BIN
stage0/stdlib/Lake/Config/Meta.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/Config/Package.c
generated
BIN
stage0/stdlib/Lake/Config/Package.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/Config/PackageConfig.c
generated
BIN
stage0/stdlib/Lake/Config/PackageConfig.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/DSL/Attributes.c
generated
BIN
stage0/stdlib/Lake/DSL/Attributes.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/DSL/Config.c
generated
BIN
stage0/stdlib/Lake/DSL/Config.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/DSL/DeclUtil.c
generated
BIN
stage0/stdlib/Lake/DSL/DeclUtil.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/DSL/Key.c
generated
BIN
stage0/stdlib/Lake/DSL/Key.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/DSL/Meta.c
generated
BIN
stage0/stdlib/Lake/DSL/Meta.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/DSL/Package.c
generated
BIN
stage0/stdlib/Lake/DSL/Package.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/DSL/Require.c
generated
BIN
stage0/stdlib/Lake/DSL/Require.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/DSL/Script.c
generated
BIN
stage0/stdlib/Lake/DSL/Script.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/DSL/Targets.c
generated
BIN
stage0/stdlib/Lake/DSL/Targets.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/Load/Lean/Elab.c
generated
BIN
stage0/stdlib/Lake/Load/Lean/Elab.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/Load/Lean/Eval.c
generated
BIN
stage0/stdlib/Lake/Load/Lean/Eval.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/Load/Manifest.c
generated
BIN
stage0/stdlib/Lake/Load/Manifest.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/Load/Materialize.c
generated
BIN
stage0/stdlib/Lake/Load/Materialize.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/Load/Package.c
generated
BIN
stage0/stdlib/Lake/Load/Package.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/Load/Resolve.c
generated
BIN
stage0/stdlib/Lake/Load/Resolve.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/Load/Toml.c
generated
BIN
stage0/stdlib/Lake/Load/Toml.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/Toml/Data/DateTime.c
generated
BIN
stage0/stdlib/Lake/Toml/Data/DateTime.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/Toml/Elab/Expression.c
generated
BIN
stage0/stdlib/Lake/Toml/Elab/Expression.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/Toml/Elab/Value.c
generated
BIN
stage0/stdlib/Lake/Toml/Elab/Value.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/Util/Date.c
generated
BIN
stage0/stdlib/Lake/Util/Date.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/Util/Family.c
generated
BIN
stage0/stdlib/Lake/Util/Family.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/Util/Log.c
generated
BIN
stage0/stdlib/Lake/Util/Log.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/Util/MainM.c
generated
BIN
stage0/stdlib/Lake/Util/MainM.c
generated
Binary file not shown.
BIN
stage0/stdlib/Lake/Util/Message.c
generated
BIN
stage0/stdlib/Lake/Util/Message.c
generated
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user