mirror of
https://github.com/leanprover/lean4.git
synced 2026-03-21 04:14:07 +00:00
Compare commits
1 Commits
forIn_toAr
...
array_modi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7b7ca92383 |
@@ -241,15 +241,12 @@ def swapAt! (a : Array α) (i : Nat) (v : α) : α × Array α :=
|
||||
have : Inhabited (α × Array α) := ⟨(v, a)⟩
|
||||
panic! ("index " ++ toString i ++ " out of bounds")
|
||||
|
||||
/-- `take a n` returns the first `n` elements of `a`. -/
|
||||
def take (a : Array α) (n : Nat) : Array α :=
|
||||
def shrink (a : Array α) (n : Nat) : Array α :=
|
||||
let rec loop
|
||||
| 0, a => a
|
||||
| n+1, a => loop n a.pop
|
||||
loop (a.size - n) a
|
||||
|
||||
@[deprecated take (since := "2024-10-22")] abbrev shrink := @take
|
||||
|
||||
@[inline]
|
||||
unsafe def modifyMUnsafe [Monad m] (a : Array α) (i : Nat) (f : α → m α) : m (Array α) := do
|
||||
if h : i < a.size then
|
||||
|
||||
@@ -9,6 +9,7 @@ import Init.Data.List.Impl
|
||||
import Init.Data.List.Monadic
|
||||
import Init.Data.List.Range
|
||||
import Init.Data.List.Nat.TakeDrop
|
||||
import Init.Data.List.Nat.Modify
|
||||
import Init.Data.Array.Mem
|
||||
import Init.TacticsExtra
|
||||
|
||||
@@ -101,25 +102,6 @@ We prefer to pull `List.toArray` outwards.
|
||||
@[simp] theorem back_toArray [Inhabited α] (l : List α) : l.toArray.back = l.getLast! := by
|
||||
simp only [back, size_toArray, Array.get!_eq_getElem!, getElem!_toArray, getLast!_eq_getElem!]
|
||||
|
||||
@[simp] theorem forIn_loop_toArray [Monad m] (l : List α) (f : α → β → m (ForInStep β)) (i : Nat)
|
||||
(h : i ≤ l.length) (b : β) :
|
||||
Array.forIn.loop l.toArray f i h b = (l.drop (l.length - i)).forIn b f := by
|
||||
induction i generalizing l b with
|
||||
| zero => simp [Array.forIn.loop]
|
||||
| succ i ih =>
|
||||
simp only [Array.forIn.loop, size_toArray, getElem_toArray, ih, forIn_eq_forIn]
|
||||
rw [Nat.sub_add_eq, List.drop_sub_one (by omega), List.getElem?_eq_getElem (by omega)]
|
||||
simp only [Option.toList_some, singleton_append, forIn_cons]
|
||||
have t : l.length - 1 - i = l.length - i - 1 := by omega
|
||||
simp only [t]
|
||||
congr
|
||||
|
||||
@[simp] theorem forIn_toArray [Monad m] (l : List α) (b : β) (f : α → β → m (ForInStep β)) :
|
||||
forIn l.toArray b f = forIn l b f := by
|
||||
change l.toArray.forIn b f = l.forIn b f
|
||||
rw [Array.forIn, forIn_loop_toArray]
|
||||
simp
|
||||
|
||||
theorem foldrM_toArray [Monad m] (f : α → β → m β) (init : β) (l : List α) :
|
||||
l.toArray.foldrM f init = l.foldrM f init := by
|
||||
rw [foldrM_eq_reverse_foldlM_toList]
|
||||
@@ -690,40 +672,6 @@ theorem getElem_range {n : Nat} {x : Nat} (h : x < (Array.range n).size) : (Arra
|
||||
true_and, Nat.not_lt] at h
|
||||
rw [List.getElem?_eq_none_iff.2 ‹_›, List.getElem?_eq_none_iff.2 (a.toList.length_reverse ▸ ‹_›)]
|
||||
|
||||
/-! ### take -/
|
||||
|
||||
@[simp] theorem size_take_loop (a : Array α) (n : Nat) : (take.loop n a).size = a.size - n := by
|
||||
induction n generalizing a with
|
||||
| zero => simp [take.loop]
|
||||
| succ n ih =>
|
||||
simp [take.loop, ih]
|
||||
omega
|
||||
|
||||
@[simp] theorem getElem_take_loop (a : Array α) (n : Nat) (i : Nat) (h : i < (take.loop n a).size) :
|
||||
(take.loop n a)[i] = a[i]'(by simp at h; omega) := by
|
||||
induction n generalizing a i with
|
||||
| zero => simp [take.loop]
|
||||
| succ n ih =>
|
||||
simp [take.loop, ih]
|
||||
|
||||
@[simp] theorem size_take (a : Array α) (n : Nat) : (a.take n).size = min n a.size := by
|
||||
simp [take]
|
||||
omega
|
||||
|
||||
@[simp] theorem getElem_take (a : Array α) (n : Nat) (i : Nat) (h : i < (a.take n).size) :
|
||||
(a.take n)[i] = a[i]'(by simp at h; omega) := by
|
||||
simp [take]
|
||||
|
||||
@[simp] theorem toList_take (a : Array α) (n : Nat) : (a.take n).toList = a.toList.take n := by
|
||||
apply List.ext_getElem <;> simp
|
||||
|
||||
/-! ### forIn -/
|
||||
|
||||
@[simp] theorem forIn_toList [Monad m] (as : Array α) (b : β) (f : α → β → m (ForInStep β)) :
|
||||
forIn as.toList b f = forIn as b f := by
|
||||
cases as
|
||||
simp
|
||||
|
||||
/-! ### foldl / foldr -/
|
||||
|
||||
@[simp] theorem foldlM_loop_empty [Monad m] (f : β → α → m β) (init : β) (i j : Nat) :
|
||||
@@ -904,6 +852,12 @@ theorem getElem_modify {as : Array α} {x i} (h : i < (as.modify x f).size) :
|
||||
· simp only [Id.bind_eq, get_set _ _ _ (by simpa using h)]; split <;> simp [*]
|
||||
· rw [if_neg (mt (by rintro rfl; exact h) (by simp_all))]
|
||||
|
||||
@[simp] theorem toList_modify (as : Array α) (f : α → α) :
|
||||
(as.modify x f).toList = as.toList.modify f x := by
|
||||
apply List.ext_getElem
|
||||
· simp
|
||||
· simp [getElem_modify, List.getElem_modify]
|
||||
|
||||
theorem getElem_modify_self {as : Array α} {i : Nat} (f : α → α) (h : i < (as.modify i f).size) :
|
||||
(as.modify i f)[i] = f (as[i]'(by simpa using h)) := by
|
||||
simp [getElem_modify h]
|
||||
@@ -1392,10 +1346,6 @@ Our goal is to have `simp` "pull `List.toArray` outwards" as much as possible.
|
||||
apply ext'
|
||||
simp
|
||||
|
||||
@[simp] theorem take_toArray (l : List α) (n : Nat) : l.toArray.take n = (l.take n).toArray := by
|
||||
apply ext'
|
||||
simp
|
||||
|
||||
@[simp] theorem mapM_toArray [Monad m] [LawfulMonad m] (f : α → m β) (l : List α) :
|
||||
l.toArray.mapM f = List.toArray <$> l.mapM f := by
|
||||
simp only [← mapM'_eq_mapM, mapM_eq_foldlM]
|
||||
@@ -1490,6 +1440,11 @@ theorem all_toArray (p : α → Bool) (l : List α) : l.toArray.all p = l.all p
|
||||
apply ext'
|
||||
simp
|
||||
|
||||
@[simp] theorem modify_toArray (f : α → α) (l : List α) :
|
||||
l.toArray.modify i f = (l.modify f i).toArray := by
|
||||
apply ext'
|
||||
simp
|
||||
|
||||
@[simp] theorem filter_toArray' (p : α → Bool) (l : List α) (h : stop = l.toArray.size) :
|
||||
l.toArray.filter p 0 stop = (l.filter p).toArray := by
|
||||
subst h
|
||||
|
||||
@@ -38,7 +38,7 @@ The operations are organized as follow:
|
||||
* Sublists: `take`, `drop`, `takeWhile`, `dropWhile`, `partition`, `dropLast`,
|
||||
`isPrefixOf`, `isPrefixOf?`, `isSuffixOf`, `isSuffixOf?`, `Subset`, `Sublist`,
|
||||
`rotateLeft` and `rotateRight`.
|
||||
* Manipulating elements: `replace`, `insert`, `erase`, `eraseP`, `eraseIdx`.
|
||||
* Manipulating elements: `replace`, `insert`, `modify`, `erase`, `eraseP`, `eraseIdx`.
|
||||
* Finding elements: `find?`, `findSome?`, `findIdx`, `indexOf`, `findIdx?`, `indexOf?`,
|
||||
`countP`, `count`, and `lookup`.
|
||||
* Logic: `any`, `all`, `or`, and `and`.
|
||||
@@ -1119,6 +1119,35 @@ theorem replace_cons [BEq α] {a : α} :
|
||||
@[inline] protected def insert [BEq α] (a : α) (l : List α) : List α :=
|
||||
if l.elem a then l else a :: l
|
||||
|
||||
/-! ### modify -/
|
||||
|
||||
/--
|
||||
Apply a function to the nth tail of `l`. Returns the input without
|
||||
using `f` if the index is larger than the length of the List.
|
||||
```
|
||||
modifyTailIdx f 2 [a, b, c] = [a, b] ++ f [c]
|
||||
```
|
||||
-/
|
||||
@[simp] def modifyTailIdx (f : List α → List α) : Nat → List α → List α
|
||||
| 0, l => f l
|
||||
| _+1, [] => []
|
||||
| n+1, a :: l => a :: modifyTailIdx f n l
|
||||
|
||||
/-- Apply `f` to the head of the list, if it exists. -/
|
||||
@[inline] def modifyHead (f : α → α) : List α → List α
|
||||
| [] => []
|
||||
| a :: l => f a :: l
|
||||
|
||||
@[simp] theorem modifyHead_nil (f : α → α) : [].modifyHead f = [] := by rw [modifyHead]
|
||||
@[simp] theorem modifyHead_cons (a : α) (l : List α) (f : α → α) :
|
||||
(a :: l).modifyHead f = f a :: l := by rw [modifyHead]
|
||||
|
||||
/--
|
||||
Apply `f` to the nth element of the list, if it exists, replacing that element with the result.
|
||||
-/
|
||||
def modify (f : α → α) : Nat → List α → List α :=
|
||||
modifyTailIdx (modifyHead f)
|
||||
|
||||
/-! ### erase -/
|
||||
|
||||
/--
|
||||
|
||||
@@ -38,7 +38,7 @@ The following operations were already given `@[csimp]` replacements in `Init/Dat
|
||||
|
||||
The following operations are given `@[csimp]` replacements below:
|
||||
`set`, `filterMap`, `foldr`, `append`, `bind`, `join`,
|
||||
`take`, `takeWhile`, `dropLast`, `replace`, `erase`, `eraseIdx`, `zipWith`,
|
||||
`take`, `takeWhile`, `dropLast`, `replace`, `modify`, `erase`, `eraseIdx`, `zipWith`,
|
||||
`enumFrom`, and `intercalate`.
|
||||
|
||||
-/
|
||||
@@ -197,6 +197,24 @@ The following operations are given `@[csimp]` replacements below:
|
||||
· simp [*]
|
||||
· intro h; rw [IH] <;> simp_all
|
||||
|
||||
/-! ### modify -/
|
||||
|
||||
/-- Tail-recursive version of `modify`. -/
|
||||
def modifyTR (f : α → α) (n : Nat) (l : List α) : List α := go l n #[] where
|
||||
/-- Auxiliary for `modifyTR`: `modifyTR.go f l n acc = acc.toList ++ modify f n l`. -/
|
||||
go : List α → Nat → Array α → List α
|
||||
| [], _, acc => acc.toList
|
||||
| a :: l, 0, acc => acc.toListAppend (f a :: l)
|
||||
| a :: l, n+1, acc => go l n (acc.push a)
|
||||
|
||||
theorem modifyTR_go_eq : ∀ l n, modifyTR.go f l n acc = acc.toList ++ modify f n l
|
||||
| [], n => by cases n <;> simp [modifyTR.go, modify]
|
||||
| a :: l, 0 => by simp [modifyTR.go, modify]
|
||||
| a :: l, n+1 => by simp [modifyTR.go, modify, modifyTR_go_eq l]
|
||||
|
||||
@[csimp] theorem modify_eq_modifyTR : @modify = @modifyTR := by
|
||||
funext α f n l; simp [modifyTR, modifyTR_go_eq]
|
||||
|
||||
/-! ### erase -/
|
||||
|
||||
/-- Tail recursive version of `List.erase`. -/
|
||||
|
||||
@@ -13,3 +13,4 @@ import Init.Data.List.Nat.Count
|
||||
import Init.Data.List.Nat.Erase
|
||||
import Init.Data.List.Nat.Find
|
||||
import Init.Data.List.Nat.BEq
|
||||
import Init.Data.List.Nat.Modify
|
||||
|
||||
102
src/Init/Data/List/Nat/Modify.lean
Normal file
102
src/Init/Data/List/Nat/Modify.lean
Normal file
@@ -0,0 +1,102 @@
|
||||
/-
|
||||
Copyright (c) 2014 Parikshit Khanna. All rights reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
Authors: Parikshit Khanna, Jeremy Avigad, Leonardo de Moura, Floris van Doorn, Mario Carneiro
|
||||
-/
|
||||
|
||||
prelude
|
||||
import Init.Data.List.Nat.TakeDrop
|
||||
|
||||
namespace List
|
||||
|
||||
/-! ### modifyHead -/
|
||||
|
||||
@[simp] theorem modifyHead_modifyHead (l : List α) (f g : α → α) :
|
||||
(l.modifyHead f).modifyHead g = l.modifyHead (g ∘ f) := by cases l <;> simp [modifyHead]
|
||||
|
||||
/-! ### modify -/
|
||||
|
||||
@[simp] theorem modify_nil (f : α → α) (n) : [].modify f n = [] := by cases n <;> rfl
|
||||
|
||||
@[simp] theorem modify_zero_cons (f : α → α) (a : α) (l : List α) :
|
||||
(a :: l).modify f 0 = f a :: l := rfl
|
||||
|
||||
@[simp] theorem modify_succ_cons (f : α → α) (a : α) (l : List α) (n) :
|
||||
(a :: l).modify f (n + 1) = a :: l.modify f n := by rfl
|
||||
|
||||
theorem modifyTailIdx_id : ∀ n (l : List α), l.modifyTailIdx id n = l
|
||||
| 0, _ => rfl
|
||||
| _+1, [] => rfl
|
||||
| n+1, a :: l => congrArg (cons a) (modifyTailIdx_id n l)
|
||||
|
||||
theorem eraseIdx_eq_modifyTailIdx : ∀ n (l : List α), eraseIdx l n = modifyTailIdx tail n l
|
||||
| 0, l => by cases l <;> rfl
|
||||
| _+1, [] => rfl
|
||||
| _+1, _ :: _ => congrArg (cons _) (eraseIdx_eq_modifyTailIdx _ _)
|
||||
|
||||
theorem getElem?_modify (f : α → α) :
|
||||
∀ n (l : List α) m, (modify f n l)[m]? = (fun a => if n = m then f a else a) <$> l[m]?
|
||||
| n, l, 0 => by cases l <;> cases n <;> simp
|
||||
| n, [], _+1 => by cases n <;> rfl
|
||||
| 0, _ :: l, m+1 => by cases h : l[m]? <;> simp [h, modify, m.succ_ne_zero.symm]
|
||||
| n+1, a :: l, m+1 => by
|
||||
simp only [modify_succ_cons, getElem?_cons_succ, Nat.reduceEqDiff, Option.map_eq_map]
|
||||
refine (getElem?_modify f n l m).trans ?_
|
||||
cases h' : l[m]? <;> by_cases h : n = m <;>
|
||||
simp [h, if_pos, if_neg, Option.map, mt Nat.succ.inj, not_false_iff, h']
|
||||
|
||||
@[simp] theorem length_modifyTailIdx (f : List α → List α) (H : ∀ l, length (f l) = length l) :
|
||||
∀ n l, length (modifyTailIdx f n l) = length l
|
||||
| 0, _ => H _
|
||||
| _+1, [] => rfl
|
||||
| _+1, _ :: _ => congrArg (·+1) (length_modifyTailIdx _ H _ _)
|
||||
|
||||
theorem modifyTailIdx_add (f : List α → List α) (n) (l₁ l₂ : List α) :
|
||||
modifyTailIdx f (l₁.length + n) (l₁ ++ l₂) = l₁ ++ modifyTailIdx f n l₂ := by
|
||||
induction l₁ <;> simp [*, Nat.succ_add]
|
||||
|
||||
@[simp] theorem length_modify (f : α → α) : ∀ n l, length (modify f n l) = length l :=
|
||||
length_modifyTailIdx _ fun l => by cases l <;> rfl
|
||||
|
||||
@[simp] theorem getElem?_modify_eq (f : α → α) (n) (l : List α) :
|
||||
(modify f n l)[n]? = f <$> l[n]? := by
|
||||
simp only [getElem?_modify, if_pos]
|
||||
|
||||
@[simp] theorem getElem?_modify_ne (f : α → α) {m n} (l : List α) (h : m ≠ n) :
|
||||
(modify f m l)[n]? = l[n]? := by
|
||||
simp only [getElem?_modify, if_neg h, id_map']
|
||||
|
||||
theorem getElem_modify (f : α → α) (n) (l : List α) (m) (h : m < (modify f n l).length) :
|
||||
(modify f n l)[m] =
|
||||
if n = m then f (l[m]'(by simp at h; omega)) else l[m]'(by simp at h; omega) := by
|
||||
rw [getElem_eq_iff, getElem?_modify]
|
||||
simp at h
|
||||
simp [h]
|
||||
|
||||
theorem modifyTailIdx_eq_take_drop (f : List α → List α) (H : f [] = []) :
|
||||
∀ n l, modifyTailIdx f n l = take n l ++ f (drop n l)
|
||||
| 0, _ => rfl
|
||||
| _ + 1, [] => H.symm
|
||||
| n + 1, b :: l => congrArg (cons b) (modifyTailIdx_eq_take_drop f H n l)
|
||||
|
||||
theorem modify_eq_take_drop (f : α → α) :
|
||||
∀ n l, modify f n l = take n l ++ modifyHead f (drop n l) :=
|
||||
modifyTailIdx_eq_take_drop _ rfl
|
||||
|
||||
theorem modify_eq_take_cons_drop (f : α → α) {n l} (h : n < length l) :
|
||||
modify f n l = take n l ++ f l[n] :: drop (n + 1) l := by
|
||||
rw [modify_eq_take_drop, drop_eq_getElem_cons h]; rfl
|
||||
|
||||
theorem exists_of_modifyTailIdx (f : List α → List α) {n} {l : List α} (h : n ≤ l.length) :
|
||||
∃ l₁ l₂, l = l₁ ++ l₂ ∧ l₁.length = n ∧ modifyTailIdx f n l = l₁ ++ f l₂ :=
|
||||
have ⟨_, _, eq, hl⟩ : ∃ l₁ l₂, l = l₁ ++ l₂ ∧ l₁.length = n :=
|
||||
⟨_, _, (take_append_drop n l).symm, length_take_of_le h⟩
|
||||
⟨_, _, eq, hl, hl ▸ eq ▸ modifyTailIdx_add (n := 0) ..⟩
|
||||
|
||||
theorem exists_of_modify (f : α → α) {n} {l : List α} (h : n < l.length) :
|
||||
∃ l₁ a l₂, l = l₁ ++ a :: l₂ ∧ l₁.length = n ∧ modify f n l = l₁ ++ f a :: l₂ :=
|
||||
match exists_of_modifyTailIdx _ (Nat.le_of_lt h) with
|
||||
| ⟨_, _::_, eq, hl, H⟩ => ⟨_, _, _, eq, hl, H⟩
|
||||
| ⟨_, [], eq, hl, _⟩ => nomatch Nat.ne_of_gt h (eq ▸ append_nil _ ▸ hl)
|
||||
|
||||
end List
|
||||
@@ -187,9 +187,6 @@ theorem take_add (l : List α) (m n : Nat) : l.take (m + n) = l.take m ++ (l.dro
|
||||
· apply length_take_le
|
||||
· apply Nat.le_add_right
|
||||
|
||||
theorem take_one {l : List α} : l.take 1 = l.head?.toList := by
|
||||
induction l <;> simp
|
||||
|
||||
theorem dropLast_take {n : Nat} {l : List α} (h : n < l.length) :
|
||||
(l.take n).dropLast = l.take (n - 1) := by
|
||||
simp only [dropLast_eq_take, length_take, Nat.le_of_lt h, Nat.min_eq_left, take_take, sub_le]
|
||||
@@ -285,14 +282,14 @@ theorem mem_drop_iff_getElem {l : List α} {a : α} :
|
||||
· rintro ⟨i, hm, rfl⟩
|
||||
refine ⟨i, by simp; omega, by rw [getElem_drop]⟩
|
||||
|
||||
@[simp] theorem head?_drop (l : List α) (n : Nat) :
|
||||
theorem head?_drop (l : List α) (n : Nat) :
|
||||
(l.drop n).head? = l[n]? := by
|
||||
rw [head?_eq_getElem?, getElem?_drop, Nat.add_zero]
|
||||
|
||||
@[simp] theorem head_drop {l : List α} {n : Nat} (h : l.drop n ≠ []) :
|
||||
theorem head_drop {l : List α} {n : Nat} (h : l.drop n ≠ []) :
|
||||
(l.drop n).head h = l[n]'(by simp_all) := by
|
||||
have w : n < l.length := length_lt_of_drop_ne_nil h
|
||||
simp [getElem?_eq_getElem, h, w, head_eq_iff_head?_eq_some]
|
||||
simpa [getElem?_eq_getElem, h, w, head_eq_iff_head?_eq_some] using head?_drop l n
|
||||
|
||||
theorem getLast?_drop {l : List α} : (l.drop n).getLast? = if l.length ≤ n then none else l.getLast? := by
|
||||
rw [getLast?_eq_getElem?, getElem?_drop]
|
||||
@@ -303,7 +300,7 @@ theorem getLast?_drop {l : List α} : (l.drop n).getLast? = if l.length ≤ n th
|
||||
congr
|
||||
omega
|
||||
|
||||
@[simp] theorem getLast_drop {l : List α} (h : l.drop n ≠ []) :
|
||||
theorem getLast_drop {l : List α} (h : l.drop n ≠ []) :
|
||||
(l.drop n).getLast h = l.getLast (ne_nil_of_length_pos (by simp at h; omega)) := by
|
||||
simp only [ne_eq, drop_eq_nil_iff] at h
|
||||
apply Option.some_inj.1
|
||||
@@ -452,26 +449,6 @@ theorem reverse_drop {l : List α} {n : Nat} :
|
||||
rw [w, take_zero, drop_of_length_le, reverse_nil]
|
||||
omega
|
||||
|
||||
theorem take_add_one {l : List α} {n : Nat} :
|
||||
l.take (n + 1) = l.take n ++ l[n]?.toList := by
|
||||
simp [take_add, take_one]
|
||||
|
||||
theorem drop_eq_getElem?_toList_append {l : List α} {n : Nat} :
|
||||
l.drop n = l[n]?.toList ++ l.drop (n + 1) := by
|
||||
induction l generalizing n with
|
||||
| nil => simp
|
||||
| cons hd tl ih =>
|
||||
cases n
|
||||
· simp
|
||||
· simp only [drop_succ_cons, getElem?_cons_succ]
|
||||
rw [ih]
|
||||
|
||||
theorem drop_sub_one {l : List α} {n : Nat} (h : 0 < n) :
|
||||
l.drop (n - 1) = l[n - 1]?.toList ++ l.drop n := by
|
||||
rw [drop_eq_getElem?_toList_append]
|
||||
congr
|
||||
omega
|
||||
|
||||
/-! ### findIdx -/
|
||||
|
||||
theorem false_of_mem_take_findIdx {xs : List α} {p : α → Bool} (h : x ∈ xs.take (xs.findIdx p)) :
|
||||
|
||||
@@ -46,7 +46,7 @@ partial def withCheckpoint (x : PullM Code) : PullM Code := do
|
||||
else
|
||||
return c
|
||||
let (c, keep) := go toPullSizeSaved (← read).included |>.run #[]
|
||||
modify fun s => { s with toPull := s.toPull.take toPullSizeSaved ++ keep }
|
||||
modify fun s => { s with toPull := s.toPull.shrink toPullSizeSaved ++ keep }
|
||||
return c
|
||||
|
||||
def attachToPull (c : Code) : PullM Code := do
|
||||
|
||||
@@ -182,7 +182,7 @@ partial def moduleIdent (runtimeOnly : Bool) : Parser := fun input s =>
|
||||
let s := p input s
|
||||
match s.error? with
|
||||
| none => many p input s
|
||||
| some _ => { pos, error? := none, imports := s.imports.take size }
|
||||
| some _ => { pos, error? := none, imports := s.imports.shrink size }
|
||||
|
||||
@[inline] partial def preludeOpt (k : String) : Parser :=
|
||||
keywordCore k (fun _ s => s.pushModule `Init false) (fun _ s => s)
|
||||
|
||||
@@ -36,8 +36,8 @@ abbrev Assignment.get? (a : Assignment) (x : Var) : Option Rat :=
|
||||
abbrev Assignment.push (a : Assignment) (v : Rat) : Assignment :=
|
||||
{ a with val := a.val.push v }
|
||||
|
||||
abbrev Assignment.take (a : Assignment) (newSize : Nat) : Assignment :=
|
||||
{ a with val := a.val.take newSize }
|
||||
abbrev Assignment.shrink (a : Assignment) (newSize : Nat) : Assignment :=
|
||||
{ a with val := a.val.shrink newSize }
|
||||
|
||||
structure Poly where
|
||||
val : Array (Int × Var)
|
||||
@@ -242,7 +242,7 @@ def resolve (s : State) (cl : Cnstr) (cu : Cnstr) : Sum Result State :=
|
||||
let maxVarIdx := c.lhs.getMaxVar.id
|
||||
match s with -- Hack: we avoid { s with ... } to make sure we get a destructive update
|
||||
| { lowers, uppers, int, assignment, } =>
|
||||
let assignment := assignment.take maxVarIdx
|
||||
let assignment := assignment.shrink maxVarIdx
|
||||
if c.lhs.getMaxVarCoeff < 0 then
|
||||
let lowers := lowers.modify maxVarIdx (·.push c)
|
||||
Sum.inr { lowers, uppers, int, assignment }
|
||||
|
||||
@@ -84,7 +84,7 @@ private def mkNullaryCtor (type : Expr) (nparams : Nat) : MetaM (Option Expr) :=
|
||||
let .const d lvls := type.getAppFn
|
||||
| return none
|
||||
let (some ctor) ← getFirstCtor d | pure none
|
||||
return mkAppN (mkConst ctor lvls) (type.getAppArgs.take nparams)
|
||||
return mkAppN (mkConst ctor lvls) (type.getAppArgs.shrink nparams)
|
||||
|
||||
private def getRecRuleFor (recVal : RecursorVal) (major : Expr) : Option RecursorRule :=
|
||||
match major.getAppFn with
|
||||
@@ -152,7 +152,7 @@ private def toCtorWhenStructure (inductName : Name) (major : Expr) : MetaM Expr
|
||||
else
|
||||
let some ctorName ← getFirstCtor d | pure major
|
||||
let ctorInfo ← getConstInfoCtor ctorName
|
||||
let params := majorType.getAppArgs.take ctorInfo.numParams
|
||||
let params := majorType.getAppArgs.shrink ctorInfo.numParams
|
||||
let mut result := mkAppN (mkConst ctorName us) params
|
||||
for i in [:ctorInfo.numFields] do
|
||||
result := mkApp result (← mkProjFn ctorInfo us params i major)
|
||||
|
||||
@@ -1305,7 +1305,7 @@ namespace ParserState
|
||||
|
||||
def keepTop (s : SyntaxStack) (startStackSize : Nat) : SyntaxStack :=
|
||||
let node := s.back
|
||||
s.take startStackSize |>.push node
|
||||
s.shrink startStackSize |>.push node
|
||||
|
||||
def keepNewError (s : ParserState) (oldStackSize : Nat) : ParserState :=
|
||||
match s with
|
||||
@@ -1314,13 +1314,13 @@ def keepNewError (s : ParserState) (oldStackSize : Nat) : ParserState :=
|
||||
def keepPrevError (s : ParserState) (oldStackSize : Nat) (oldStopPos : String.Pos) (oldError : Option Error) (oldLhsPrec : Nat) : ParserState :=
|
||||
match s with
|
||||
| ⟨stack, _, _, cache, _, errs⟩ =>
|
||||
⟨stack.take oldStackSize, oldLhsPrec, oldStopPos, cache, oldError, errs⟩
|
||||
⟨stack.shrink oldStackSize, oldLhsPrec, oldStopPos, cache, oldError, errs⟩
|
||||
|
||||
def mergeErrors (s : ParserState) (oldStackSize : Nat) (oldError : Error) : ParserState :=
|
||||
match s with
|
||||
| ⟨stack, lhsPrec, pos, cache, some err, errs⟩ =>
|
||||
let newError := if oldError == err then err else oldError.merge err
|
||||
⟨stack.take oldStackSize, lhsPrec, pos, cache, some newError, errs⟩
|
||||
⟨stack.shrink oldStackSize, lhsPrec, pos, cache, some newError, errs⟩
|
||||
| other => other
|
||||
|
||||
def keepLatest (s : ParserState) (startStackSize : Nat) : ParserState :=
|
||||
@@ -1363,7 +1363,7 @@ def runLongestMatchParser (left? : Option Syntax) (startLhsPrec : Nat) (p : Pars
|
||||
s -- success or error with the expected number of nodes
|
||||
else if s.hasError then
|
||||
-- error with an unexpected number of nodes.
|
||||
s.takeStack startSize |>.pushSyntax Syntax.missing
|
||||
s.shrinkStack startSize |>.pushSyntax Syntax.missing
|
||||
else
|
||||
-- parser succeeded with incorrect number of nodes
|
||||
invalidLongestMatchParser s
|
||||
|
||||
@@ -158,10 +158,8 @@ def size (stack : SyntaxStack) : Nat :=
|
||||
def isEmpty (stack : SyntaxStack) : Bool :=
|
||||
stack.size == 0
|
||||
|
||||
def take (stack : SyntaxStack) (n : Nat) : SyntaxStack :=
|
||||
{ stack with raw := stack.raw.take (stack.drop + n) }
|
||||
|
||||
@[deprecated take (since := "2024-10-22")] abbrev shrink := @take
|
||||
def shrink (stack : SyntaxStack) (n : Nat) : SyntaxStack :=
|
||||
{ stack with raw := stack.raw.shrink (stack.drop + n) }
|
||||
|
||||
def push (stack : SyntaxStack) (a : Syntax) : SyntaxStack :=
|
||||
{ stack with raw := stack.raw.push a }
|
||||
@@ -214,7 +212,7 @@ def stackSize (s : ParserState) : Nat :=
|
||||
s.stxStack.size
|
||||
|
||||
def restore (s : ParserState) (iniStackSz : Nat) (iniPos : String.Pos) : ParserState :=
|
||||
{ s with stxStack := s.stxStack.take iniStackSz, errorMsg := none, pos := iniPos }
|
||||
{ s with stxStack := s.stxStack.shrink iniStackSz, errorMsg := none, pos := iniPos }
|
||||
|
||||
def setPos (s : ParserState) (pos : String.Pos) : ParserState :=
|
||||
{ s with pos := pos }
|
||||
@@ -228,10 +226,8 @@ def pushSyntax (s : ParserState) (n : Syntax) : ParserState :=
|
||||
def popSyntax (s : ParserState) : ParserState :=
|
||||
{ s with stxStack := s.stxStack.pop }
|
||||
|
||||
def takeStack (s : ParserState) (iniStackSz : Nat) : ParserState :=
|
||||
{ s with stxStack := s.stxStack.take iniStackSz }
|
||||
|
||||
@[deprecated takeStack (since := "2024-10-22")] abbrev shrinkStack := @takeStack
|
||||
def shrinkStack (s : ParserState) (iniStackSz : Nat) : ParserState :=
|
||||
{ s with stxStack := s.stxStack.shrink iniStackSz }
|
||||
|
||||
def next (s : ParserState) (input : String) (pos : String.Pos) : ParserState :=
|
||||
{ s with pos := input.next pos }
|
||||
@@ -254,7 +250,7 @@ def mkNode (s : ParserState) (k : SyntaxNodeKind) (iniStackSz : Nat) : ParserSta
|
||||
⟨stack, lhsPrec, pos, cache, err, recovered⟩
|
||||
else
|
||||
let newNode := Syntax.node SourceInfo.none k (stack.extract iniStackSz stack.size)
|
||||
let stack := stack.take iniStackSz
|
||||
let stack := stack.shrink iniStackSz
|
||||
let stack := stack.push newNode
|
||||
⟨stack, lhsPrec, pos, cache, err, recovered⟩
|
||||
|
||||
@@ -262,7 +258,7 @@ def mkTrailingNode (s : ParserState) (k : SyntaxNodeKind) (iniStackSz : Nat) : P
|
||||
match s with
|
||||
| ⟨stack, lhsPrec, pos, cache, err, errs⟩ =>
|
||||
let newNode := Syntax.node SourceInfo.none k (stack.extract (iniStackSz - 1) stack.size)
|
||||
let stack := stack.take (iniStackSz - 1)
|
||||
let stack := stack.shrink (iniStackSz - 1)
|
||||
let stack := stack.push newNode
|
||||
⟨stack, lhsPrec, pos, cache, err, errs⟩
|
||||
|
||||
@@ -287,7 +283,7 @@ def mkEOIError (s : ParserState) (expected : List String := []) : ParserState :=
|
||||
def mkErrorsAt (s : ParserState) (ex : List String) (pos : String.Pos) (initStackSz? : Option Nat := none) : ParserState := Id.run do
|
||||
let mut s := s.setPos pos
|
||||
if let some sz := initStackSz? then
|
||||
s := s.takeStack sz
|
||||
s := s.shrinkStack sz
|
||||
s := s.setError { expected := ex }
|
||||
s.pushSyntax .missing
|
||||
|
||||
|
||||
@@ -398,7 +398,7 @@ mutual
|
||||
let fType ← replaceLPsWithVars (← inferType f)
|
||||
let (mvars, bInfos, resultType) ← forallMetaBoundedTelescope fType args.size
|
||||
let rest := args.extract mvars.size args.size
|
||||
let args := args.take mvars.size
|
||||
let args := args.shrink mvars.size
|
||||
|
||||
-- Unify with the expected type
|
||||
if (← read).knowsType then tryUnify (← inferType (mkAppN f args)) resultType
|
||||
|
||||
@@ -144,7 +144,7 @@ def fold (fn : Array Format → Format) (x : FormatterM Unit) : FormatterM Unit
|
||||
x
|
||||
let stack ← getStack
|
||||
let f := fn $ stack.extract sp stack.size
|
||||
setStack $ (stack.take sp).push f
|
||||
setStack $ (stack.shrink sp).push f
|
||||
|
||||
/-- Execute `x` and concatenate generated Format objects. -/
|
||||
def concat (x : FormatterM Unit) : FormatterM Unit := do
|
||||
|
||||
@@ -292,7 +292,7 @@ instance : Append Log := ⟨Log.append⟩
|
||||
|
||||
/-- Removes log entries after `pos` (inclusive). -/
|
||||
@[inline] def dropFrom (log : Log) (pos : Log.Pos) : Log :=
|
||||
.mk <| log.entries.take pos.val
|
||||
.mk <| log.entries.shrink pos.val
|
||||
|
||||
/-- Takes log entries before `pos` (exclusive). -/
|
||||
@[inline] def takeFrom (log : Log) (pos : Log.Pos) : Log :=
|
||||
|
||||
@@ -5,11 +5,3 @@
|
||||
#check_simp #[1,2,3,4,5][2]! ~> 3
|
||||
#check_simp #[1,2,3,4,5][7]! ~> (default : Nat)
|
||||
#check_simp (#[] : Array Nat)[0]! ~> (default : Nat)
|
||||
|
||||
attribute [local simp] Id.run in
|
||||
#check_simp
|
||||
(Id.run do
|
||||
let mut s := 0
|
||||
for i in [1,2,3,4].toArray do
|
||||
s := s + i
|
||||
pure s) ~> 10
|
||||
|
||||
@@ -64,7 +64,7 @@ d.errorMsg != none
|
||||
d.stxStack.size
|
||||
|
||||
def ParserData.restore (d : ParserData) (iniStackSz : Nat) (iniPos : Nat) : ParserData :=
|
||||
{ stxStack := d.stxStack.take iniStackSz, errorMsg := none, pos := iniPos, .. d}
|
||||
{ stxStack := d.stxStack.shrink iniStackSz, errorMsg := none, pos := iniPos, .. d}
|
||||
|
||||
def ParserData.setPos (d : ParserData) (pos : Nat) : ParserData :=
|
||||
{ pos := pos, .. d }
|
||||
@@ -75,8 +75,8 @@ def ParserData.setCache (d : ParserData) (cache : ParserCache) : ParserData :=
|
||||
def ParserData.pushSyntax (d : ParserData) (n : Syntax) : ParserData :=
|
||||
{ stxStack := d.stxStack.push n, .. d }
|
||||
|
||||
def ParserData.takeStack (d : ParserData) (iniStackSz : Nat) : ParserData :=
|
||||
{ stxStack := d.stxStack.take iniStackSz, .. d }
|
||||
def ParserData.shrinkStack (d : ParserData) (iniStackSz : Nat) : ParserData :=
|
||||
{ stxStack := d.stxStack.shrink iniStackSz, .. d }
|
||||
|
||||
def ParserData.next (d : ParserData) (s : String) (pos : Nat) : ParserData :=
|
||||
{ pos := s.next pos, .. d }
|
||||
@@ -114,7 +114,7 @@ match d with
|
||||
d
|
||||
else
|
||||
let newNode := Syntax.node k (stack.extract iniStackSz stack.size) [] in
|
||||
let stack := stack.take iniStackSz in
|
||||
let stack := stack.shrink iniStackSz in
|
||||
let stack := stack.push newNode in
|
||||
⟨stack, pos, cache, err⟩
|
||||
|
||||
@@ -144,7 +144,7 @@ match d with
|
||||
let iniSz := d.stackSize in
|
||||
let iniPos := d.pos in
|
||||
match p s d with
|
||||
| ⟨stack, _, cache, some msg⟩ := ⟨stack.take iniSz, iniPos, cache, some msg⟩
|
||||
| ⟨stack, _, cache, some msg⟩ := ⟨stack.shrink iniSz, iniPos, cache, some msg⟩
|
||||
| other := other
|
||||
|
||||
@[noinline] def noFirstTokenInfo (info : ParserInfo) : ParserInfo :=
|
||||
@@ -516,15 +516,15 @@ partial def identFnAux (startPos : Nat) (tk : Option TokenConfig) : Name → Par
|
||||
|
||||
def ParserData.keepNewError (d : ParserData) (oldStackSize : Nat) : ParserData :=
|
||||
match d with
|
||||
| ⟨stack, pos, cache, err⟩ := ⟨stack.take oldStackSize, pos, cache, err⟩
|
||||
| ⟨stack, pos, cache, err⟩ := ⟨stack.shrink oldStackSize, pos, cache, err⟩
|
||||
|
||||
def ParserData.keepPrevError (d : ParserData) (oldStackSize : Nat) (oldStopPos : String.Pos) (oldError : Option String) : ParserData :=
|
||||
match d with
|
||||
| ⟨stack, _, cache, _⟩ := ⟨stack.take oldStackSize, oldStopPos, cache, oldError⟩
|
||||
| ⟨stack, _, cache, _⟩ := ⟨stack.shrink oldStackSize, oldStopPos, cache, oldError⟩
|
||||
|
||||
def ParserData.mergeErrors (d : ParserData) (oldStackSize : Nat) (oldError : String) : ParserData :=
|
||||
match d with
|
||||
| ⟨stack, pos, cache, some err⟩ := ⟨stack.take oldStackSize, pos, cache, some (err ++ "; " ++ oldError)⟩
|
||||
| ⟨stack, pos, cache, some err⟩ := ⟨stack.shrink oldStackSize, pos, cache, some (err ++ "; " ++ oldError)⟩
|
||||
| other := other
|
||||
|
||||
def ParserData.mkLongestNodeAlt (d : ParserData) (startSize : Nat) : ParserData :=
|
||||
@@ -535,14 +535,14 @@ match d with
|
||||
else
|
||||
-- parser created more than one node, combine them into a single node
|
||||
let node := Syntax.node nullKind (stack.extract startSize stack.size) [] in
|
||||
let stack := stack.take startSize in
|
||||
let stack := stack.shrink startSize in
|
||||
⟨stack.push node, pos, cache, none⟩
|
||||
|
||||
def ParserData.keepLatest (d : ParserData) (startStackSize : Nat) : ParserData :=
|
||||
match d with
|
||||
| ⟨stack, pos, cache, _⟩ :=
|
||||
let node := stack.back in
|
||||
let stack := stack.take startStackSize in
|
||||
let stack := stack.shrink startStackSize in
|
||||
let stack := stack.push node in
|
||||
⟨stack, pos, cache, none⟩
|
||||
|
||||
@@ -591,7 +591,7 @@ def longestMatchFn₂ (p q : ParserFn) : ParserFn :=
|
||||
let startSize := d.stackSize in
|
||||
let startPos := d.pos in
|
||||
let d := p s d in
|
||||
let d := if d.hasError then d.takeStack startSize else d.mkLongestNodeAlt startSize in
|
||||
let d := if d.hasError then d.shrinkStack startSize else d.mkLongestNodeAlt startSize in
|
||||
let d := longestMatchStep startSize startPos q s d in
|
||||
longestMatchMkResult startSize d
|
||||
|
||||
@@ -603,7 +603,7 @@ def longestMatchFn : List ParserFn → ParserFn
|
||||
let startPos := d.pos in
|
||||
let d := p s d in
|
||||
if d.hasError then
|
||||
let d := d.takeStack startSize in
|
||||
let d := d.shrinkStack startSize in
|
||||
longestMatchFnAux startSize startPos ps s d
|
||||
else
|
||||
let d := d.mkLongestNodeAlt startSize in
|
||||
|
||||
Reference in New Issue
Block a user