Skip to content

Commit d8913f8

Browse files
authored
feat: move String positions between slices (#11380)
This PR renames `String.Slice.Pos.ofSlice` to `String.Pos.ofToSlice` to adhere with the (yet-to-be documented) naming convention for mapping positions to positions. It then adds several new functions so that for every way to construct a slice from a string and slice, there are now functions for mapping positions forwards and backwards along this construction.
1 parent 9ce8a06 commit d8913f8

File tree

2 files changed

+171
-55
lines changed

2 files changed

+171
-55
lines changed

src/Init/Data/String/Basic.lean

Lines changed: 164 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1104,7 +1104,7 @@ def Slice.slice? (s : Slice) (newStart newEnd : s.Pos) : Option Slice :=
11041104
/-- Given a slice and two valid positions within the slice, obtain a new slice on the same underlying
11051105
string formed by the new bounds, or panic if the given end is strictly less than the given start. -/
11061106
def Slice.slice! (s : Slice) (newStart newEnd : s.Pos) : Slice :=
1107-
if h : newStart.offset ≤ newEnd.offset then
1107+
if h : newStart ≤ newEnd then
11081108
s.slice newStart newEnd h
11091109
else
11101110
panic! "Starting position must be less than or equal to end position."
@@ -1219,12 +1219,12 @@ theorem Pos.offset_toSlice {s : String} {pos : s.Pos} : pos.toSlice.offset = pos
12191219
/-- Given a string `s`, turns a valid position on the slice `s.toSlice` into a valid position on the
12201220
string `s`. -/
12211221
@[inline, expose]
1222-
def Slice.Pos.ofSlice {s : String} (pos : s.toSlice.Pos) : s.Pos where
1222+
def Pos.ofToSlice {s : String} (pos : s.toSlice.Pos) : s.Pos where
12231223
offset := pos.offset
12241224
isValid := pos.isValidForSlice.ofSlice
12251225

12261226
@[simp]
1227-
theorem Slice.Pos.offset_ofSlice {s : String} {pos : s.toSlice.Pos} : pos.ofSlice.offset = pos.offset := (rfl)
1227+
theorem Pos.offset_ofToSlice {s : String} {pos : s.toSlice.Pos} : (ofToSlice pos).offset = pos.offset := (rfl)
12281228

12291229
@[simp]
12301230
theorem rawEndPos_toSlice {s : String} : s.toSlice.rawEndPos = s.rawEndPos := by
@@ -1239,44 +1239,44 @@ theorem startPos_toSlice {s : String} : s.toSlice.startPos = s.startPos.toSlice
12391239
Slice.Pos.ext (by simp)
12401240

12411241
@[simp]
1242-
theorem Pos.ofSlice_toSlice {s : String} (pos : s.Pos) : pos.toSlice.ofSlice = pos :=
1242+
theorem Pos.ofToSlice_toSlice {s : String} (pos : s.Pos) : (ofToSlice pos.toSlice) = pos :=
12431243
Pos.ext (by simp)
12441244

12451245
@[simp]
1246-
theorem Slice.Pos.toSlice_ofSlice {s : String} (pos : s.toSlice.Pos) : pos.ofSlice.toSlice = pos :=
1246+
theorem Slice.Pos.toSlice_ofToSlice {s : String} (pos : s.toSlice.Pos) : (Pos.ofToSlice pos).toSlice = pos :=
12471247
Slice.Pos.ext (by simp)
12481248

12491249
@[simp]
1250-
theorem Slice.Pos.toSlice_comp_ofSlice {s : String} :
1251-
Pos.toSlice ∘ (ofSlice (s := s)) = id := by ext; simp
1250+
theorem Pos.toSlice_comp_ofToSlice {s : String} :
1251+
Pos.toSlice ∘ (Pos.ofToSlice (s := s)) = id := by ext; simp
12521252

12531253
@[simp]
1254-
theorem Pos.ofSlice_comp_toSlice {s : String} :
1255-
Slice.Pos.ofSlice ∘ (toSlice (s := s)) = id := by ext; simp
1254+
theorem Pos.ofToSlice_comp_toSlice {s : String} :
1255+
Pos.ofToSlice ∘ (toSlice (s := s)) = id := by ext; simp
12561256

12571257
theorem Pos.toSlice_inj {s : String} {p q : s.Pos} : p.toSlice = q.toSlice ↔ p = q :=
1258-
fun h => by simpa using congrArg Slice.Pos.ofSlice h, (· ▸ rfl)⟩
1258+
fun h => by simpa using congrArg Pos.ofToSlice h, (· ▸ rfl)⟩
12591259

1260-
theorem Slice.Pos.ofSlice_inj {s : String} {p q : s.toSlice.Pos} : p.ofSlice = q.ofSlice ↔ p = q :=
1260+
theorem Pos.ofToSlice_inj {s : String} {p q : s.toSlice.Pos} : ofToSlice p = ofToSlice q ↔ p = q :=
12611261
fun h => by simpa using congrArg Pos.toSlice h, (· ▸ rfl)⟩
12621262

12631263
@[simp]
12641264
theorem Pos.toSlice_le {s : String} {p q : s.Pos} : p.toSlice ≤ q.toSlice ↔ p ≤ q := by
12651265
simp [le_iff, Slice.Pos.le_iff]
12661266

12671267
@[simp]
1268-
theorem Slice.Pos.ofSlice_le {s : String} {p q : s.toSlice.Pos} :
1269-
p.ofSliceq.ofSlice ↔ p ≤ q := by
1270-
simp [String.Pos.le_iff, le_iff]
1268+
theorem Pos.ofToSlice_le {s : String} {p q : s.toSlice.Pos} :
1269+
ofToSlice pofToSlice q ↔ p ≤ q := by
1270+
simp [le_iff, Slice.Pos.le_iff]
12711271

12721272
@[simp]
12731273
theorem Pos.toSlice_lt {s : String} {p q : s.Pos} : p.toSlice < q.toSlice ↔ p < q := by
12741274
simp [lt_iff, Slice.Pos.lt_iff]
12751275

12761276
@[simp]
1277-
theorem Slice.Pos.ofSlice_lt {s : String} {p q : s.toSlice.Pos} :
1278-
p.ofSlice < q.ofSlice ↔ p < q := by
1279-
simp [String.Pos.lt_iff, lt_iff]
1277+
theorem Pos.ofToSlice_lt {s : String} {p q : s.toSlice.Pos} :
1278+
ofToSlice p < ofToSlice q ↔ p < q := by
1279+
simp [lt_iff, Slice.Pos.lt_iff]
12801280

12811281
/--
12821282
Returns the character at the position `pos` of a string, taking a proof that `p` is not the
@@ -1290,7 +1290,7 @@ Examples:
12901290
-/
12911291
@[inline, expose]
12921292
def Pos.get {s : String} (pos : s.Pos) (h : pos ≠ s.endPos) : Char :=
1293-
pos.toSlice.get (ne_of_apply_ne Slice.Pos.ofSlice (by simp [h]))
1293+
pos.toSlice.get (ne_of_apply_ne Pos.ofToSlice (by simp [h]))
12941294

12951295
/--
12961296
Returns the character at the position `pos` of a string, or `none` if the position is the
@@ -1317,7 +1317,7 @@ Returns the byte at the position `pos` of a string.
13171317
-/
13181318
@[inline, expose]
13191319
def Pos.byte {s : String} (pos : s.Pos) (h : pos ≠ s.endPos) : UInt8 :=
1320-
pos.toSlice.byte (ne_of_apply_ne Slice.Pos.ofSlice (by simp [h]))
1320+
pos.toSlice.byte (ne_of_apply_ne Pos.ofToSlice (by simp [h]))
13211321

13221322
theorem Pos.isUTF8FirstByte_byte {s : String} {pos : s.Pos} {h : pos ≠ s.endPos} :
13231323
(pos.byte h).IsUTF8FirstByte :=
@@ -1661,60 +1661,56 @@ def Slice.pos! (s : Slice) (off : String.Pos.Raw) : s.Pos :=
16611661
position is not the past-the-end position, which guarantees that such a position exists. -/
16621662
@[expose, extern "lean_string_utf8_next_fast"]
16631663
def Pos.next {s : @& String} (pos : @& s.Pos) (h : pos ≠ s.endPos) : s.Pos :=
1664-
(Slice.Pos.next pos.toSlice (ne_of_apply_ne Slice.Pos.ofSlice (by simpa))).ofSlice
1664+
ofToSlice (Slice.Pos.next pos.toSlice (ne_of_apply_ne Pos.ofToSlice (by simpa)))
16651665

16661666
@[simp]
16671667
theorem Slice.Pos.str_inj {s : Slice} (p₁ p₂ : s.Pos) : p₁.str = p₂.str ↔ p₁ = p₂ := by
16681668
simp [Slice.Pos.ext_iff, String.Pos.ext_iff, Pos.Raw.ext_iff]
16691669

1670-
@[expose, extern "lean_string_utf8_next_fast"]
1671-
def String.Pos.next {s : @& String} (pos : @& s.Pos) (h : pos ≠ s.endPos) : s.Pos :=
1672-
(Slice.Pos.next pos.toSlice (ne_of_apply_ne Slice.Pos.ofSlice (by simpa))).ofSlice
1673-
16741670
/-- Advances a valid position on a string to the next valid position, or returns `none` if the
16751671
given position is the past-the-end position. -/
16761672
@[inline, expose]
16771673
def Pos.next? {s : String} (pos : s.Pos) : Option s.Pos :=
1678-
pos.toSlice.next?.map Slice.Pos.ofSlice
1674+
pos.toSlice.next?.map Pos.ofToSlice
16791675

16801676
/-- Advances a valid position on a string to the next valid position, or panics if the given
16811677
position is the past-the-end position. -/
16821678
@[inline, expose]
16831679
def Pos.next! {s : String} (pos : s.Pos) : s.Pos :=
1684-
pos.toSlice.next!.ofSlice
1680+
ofToSlice pos.toSlice.next!
16851681

16861682
/-- Returns the previous valid position before the given position, given a proof that the position
16871683
is not the start position, which guarantees that such a position exists. -/
16881684
@[inline, expose]
16891685
def Pos.prev {s : String} (pos : s.Pos) (h : pos ≠ s.startPos) : s.Pos :=
1690-
(pos.toSlice.prev (ne_of_apply_ne Slice.Pos.ofSlice (by simpa))).ofSlice
1686+
ofToSlice (pos.toSlice.prev (ne_of_apply_ne Pos.ofToSlice (by simpa)))
16911687

16921688
/-- Returns the previous valid position before the given position, or `none` if the position is
16931689
the start position. -/
16941690
@[inline, expose]
16951691
def Pos.prev? {s : String} (pos : s.Pos) : Option s.Pos :=
1696-
pos.toSlice.prev?.map Slice.Pos.ofSlice
1692+
pos.toSlice.prev?.map Pos.ofToSlice
16971693

16981694
/-- Returns the previous valid position before the given position, or panics if the position is
16991695
the start position. -/
17001696
@[inline, expose]
17011697
def Pos.prev! {s : String} (pos : s.Pos) : s.Pos :=
1702-
pos.toSlice.prev!.ofSlice
1698+
ofToSlice pos.toSlice.prev!
17031699

17041700
/-- Constructs a valid position on `s` from a position and a proof that it is valid. -/
17051701
@[inline, expose]
17061702
def pos (s : String) (off : Pos.Raw) (h : off.IsValid s) : s.Pos :=
1707-
(s.toSlice.pos off h.toSlice).ofSlice
1703+
Pos.ofToSlice (s.toSlice.pos off h.toSlice)
17081704

17091705
/-- Constructs a valid position on `s` from a position, returning `none` if the position is not valid. -/
17101706
@[inline, expose]
17111707
def pos? (s : String) (off : Pos.Raw) : Option s.Pos :=
1712-
(s.toSlice.pos? off).map Slice.Pos.ofSlice
1708+
(s.toSlice.pos? off).map Pos.ofToSlice
17131709

17141710
/-- Constructs a valid position `s` from a position, panicking if the position is not valid. -/
17151711
@[inline, expose]
17161712
def pos! (s : String) (off : Pos.Raw) : s.Pos :=
1717-
(s.toSlice.pos! off).ofSlice
1713+
Pos.ofToSlice (s.toSlice.pos! off)
17181714

17191715
@[simp]
17201716
theorem offset_pos {s : String} {off : Pos.Raw} {h} : (s.pos off h).offset = off := rfl
@@ -1814,10 +1810,10 @@ theorem Slice.Pos.prev_ne_endPos {s : Slice} {p : s.Pos} {h} : p.prev h ≠ s.en
18141810

18151811
@[simp]
18161812
theorem Pos.prev_ne_endPos {s : String} {p : s.Pos} {h} : p.prev h ≠ s.endPos :=
1817-
mt (congrArg (·.toSlice)) (Slice.Pos.prev_ne_endPos (h := mt (congrArg (·.ofSlice)) h))
1813+
mt (congrArg (·.toSlice)) (Slice.Pos.prev_ne_endPos (h := mt (congrArg Pos.ofToSlice) (by simpa)))
18181814

18191815
theorem Pos.toSlice_prev {s : String} {p : s.Pos} {h} :
1820-
(p.prev h).toSlice = p.toSlice.prev (ne_of_apply_ne Slice.Pos.ofSlice (by simpa)) := by
1816+
(p.prev h).toSlice = p.toSlice.prev (ne_of_apply_ne Pos.ofToSlice (by simpa)) := by
18211817
simp [prev]
18221818

18231819
theorem Slice.Pos.offset_prev_lt_offset {s : Slice} {p : s.Pos} {h} : (p.prev h).offset < p.offset := by
@@ -1936,7 +1932,7 @@ theorem Pos.get_toSlice {s : String} {p : s.Pos} {h} :
19361932
rfl
19371933

19381934
theorem Pos.get_eq_get_toSlice {s : String} {p : s.Pos} {h} :
1939-
p.get h = p.toSlice.get (ne_of_apply_ne Slice.Pos.ofSlice (by simp [h])) := rfl
1935+
p.get h = p.toSlice.get (ne_of_apply_ne Pos.ofToSlice (by simp [h])) := rfl
19401936

19411937
@[simp]
19421938
theorem Pos.offset_next {s : String} (p : s.Pos) (h : p ≠ s.endPos) :
@@ -1948,7 +1944,7 @@ theorem Pos.byteIdx_offset_next {s : String} (p : s.Pos) (h : p ≠ s.endPos) :
19481944
simp
19491945

19501946
theorem Pos.toSlice_next {s : String} {p : s.Pos} {h} :
1951-
(p.next h).toSlice = p.toSlice.next (ne_of_apply_ne Slice.Pos.ofSlice (by simpa)) := by
1947+
(p.next h).toSlice = p.toSlice.next (ne_of_apply_ne Pos.ofToSlice (by simpa)) := by
19521948
simp [next]
19531949

19541950
theorem Pos.byteIdx_lt_utf8ByteSize {s : String} (p : s.Pos) (h : p ≠ s.endPos) :
@@ -2052,15 +2048,15 @@ theorem Slice.Pos.next_le_of_lt {s : Slice} {p q : s.Pos} {h} : p < q → p.next
20522048
· have := (p.next h).str.isValid.le_utf8ByteSize
20532049
simpa [Nat.add_assoc] using this
20542050

2055-
theorem Slice.Pos.ofSlice_le_iff {s : String} {p : s.toSlice.Pos} {q : s.Pos} :
2056-
p.ofSlice ≤ q ↔ p ≤ q.toSlice := Iff.rfl
2051+
theorem Pos.ofToSlice_le_iff {s : String} {p : s.toSlice.Pos} {q : s.Pos} :
2052+
ofToSlice p ≤ q ↔ p ≤ q.toSlice := Iff.rfl
20572053

20582054
@[simp]
20592055
theorem Pos.toSlice_lt_toSlice_iff {s : String} {p q : s.Pos} :
20602056
p.toSlice < q.toSlice ↔ p < q := Iff.rfl
20612057

20622058
theorem Pos.next_le_of_lt {s : String} {p q : s.Pos} {h} : p < q → p.next h ≤ q := by
2063-
rw [next, Slice.Pos.ofSlice_le_iff, ← Pos.toSlice_lt_toSlice_iff]
2059+
rw [next, Pos.ofToSlice_le_iff, ← Pos.toSlice_lt_toSlice_iff]
20642060
exact Slice.Pos.next_le_of_lt
20652061

20662062
theorem Slice.Pos.get_eq_get_str {s : Slice} {p : s.Pos} {h} :
@@ -2159,23 +2155,22 @@ This happens to be equivalent to the constructor of `String.Slice`.
21592155
-/
21602156
@[inline, expose] -- For the defeq `(s.slice p₁ p₂).str = s`
21612157
def slice (s : String) (startInclusive endExclusive : s.Pos)
2162-
(h : startInclusive ≤ endExclusive) : String.Slice where
2163-
str := s
2164-
startInclusive
2165-
endExclusive
2166-
startInclusive_le_endExclusive := h
2158+
(h : startInclusive ≤ endExclusive) : String.Slice :=
2159+
s.toSlice.slice startInclusive.toSlice endExclusive.toSlice (by simpa)
21672160

21682161
@[simp]
21692162
theorem str_slice {s : String} {startInclusive endExclusive h} :
21702163
(s.slice startInclusive endExclusive h).str = s := rfl
21712164

21722165
@[simp]
21732166
theorem startInclusive_slice {s : String} {startInclusive endExclusive h} :
2174-
(s.slice startInclusive endExclusive h).startInclusive = startInclusive := rfl
2167+
(s.slice startInclusive endExclusive h).startInclusive = startInclusive := by
2168+
simp [slice]
21752169

21762170
@[simp]
21772171
theorem endExclusive_slice {s : String} {startInclusive endExclusive h} :
2178-
(s.slice startInclusive endExclusive h).endExclusive = endExclusive := rfl
2172+
(s.slice startInclusive endExclusive h).endExclusive = endExclusive := by
2173+
simp [slice]
21792174

21802175
/-- Given a string and two valid positions within the string, obtain a slice on the string formed
21812176
by the new bounds, or return `none` if the given end is strictly less then the given start. -/
@@ -2311,6 +2306,127 @@ def Pos.toReplaceEnd {s : String} (p₀ : s.Pos) (pos : s.Pos) (h : pos ≤ p₀
23112306
theorem Pos.offset_sliceTo {s : String} {p₀ : s.Pos} {pos : s.Pos} {h : pos ≤ p₀} :
23122307
(sliceTo p₀ pos h).offset = pos.offset := (rfl)
23132308

2309+
theorem Pos.Raw.isValidForSlice_slice {s : Slice} {p₀ p₁ : s.Pos} {h} (pos : Pos.Raw) :
2310+
pos.IsValidForSlice (s.slice p₀ p₁ h) ↔
2311+
pos.offsetBy p₀.offset ≤ p₁.offset ∧ (pos.offsetBy p₀.offset).IsValidForSlice s := by
2312+
refine ⟨fun ⟨h₁, h₂⟩ => ?_, fun ⟨h₁, h₂⟩ => ⟨?_, ?_⟩⟩
2313+
· have : pos.offsetBy p₀.offset ≤ p₁.offset := by
2314+
simp [Slice.Pos.le_iff, Pos.Raw.le_iff, Slice.utf8ByteSize_eq] at h h₁ ⊢
2315+
omega
2316+
exact ⟨this, ⟨Pos.Raw.le_trans this p₁.isValidForSlice.le_rawEndPos, by simpa [offsetBy_assoc]⟩⟩
2317+
· simp [Slice.Pos.le_iff, Pos.Raw.le_iff, Slice.utf8ByteSize_eq] at h h₁ ⊢
2318+
omega
2319+
· simpa [offsetBy_assoc] using h₂.isValid_offsetBy
2320+
2321+
theorem Pos.Raw.isValidForSlice_stringSlice {s : String} {p₀ p₁ : s.Pos} {h} (pos : Pos.Raw) :
2322+
pos.IsValidForSlice (s.slice p₀ p₁ h) ↔
2323+
pos.offsetBy p₀.offset ≤ p₁.offset ∧ (pos.offsetBy p₀.offset).IsValid s := by
2324+
simp [slice, isValidForSlice_slice]
2325+
2326+
/-- Given a position in `s.slice p₀ p₁ h`, obtain the corresponding position in `s`. -/
2327+
@[inline]
2328+
def Slice.Pos.ofSlice {s : Slice} {p₀ p₁ : s.Pos} {h} (pos : (s.slice p₀ p₁ h).Pos) : s.Pos where
2329+
offset := pos.offset.offsetBy p₀.offset
2330+
isValidForSlice := (Pos.Raw.isValidForSlice_slice _).1 pos.isValidForSlice |>.2
2331+
@[simp]
2332+
theorem Slice.Pos.offset_ofSlice {s : Slice} {p₀ p₁ : s.Pos} {h} {pos : (s.slice p₀ p₁ h).Pos} :
2333+
(Pos.ofSlice pos).offset = pos.offset.offsetBy p₀.offset := (rfl)
2334+
2335+
/-- Given a position in `s.slice p₀ p₁ h`, obtain the corresponding position in `s`. -/
2336+
@[inline]
2337+
def Pos.ofSlice {s : String} {p₀ p₁ : s.Pos} {h} (pos : (s.slice p₀ p₁ h).Pos) : s.Pos :=
2338+
ofToSlice (Slice.Pos.ofSlice pos)
2339+
2340+
@[simp]
2341+
theorem Pos.offset_ofSlice {s : String} {p₀ p₁ : s.Pos} {h} {pos : (s.slice p₀ p₁ h).Pos} :
2342+
(Pos.ofSlice pos).offset = pos.offset.offsetBy p₀.offset := (rfl)
2343+
2344+
theorem Slice.Pos.le_trans {s : Slice} {p q r : s.Pos} : p ≤ q → q ≤ r → p ≤ r := by
2345+
simpa [Pos.le_iff, Pos.Raw.le_iff] using Nat.le_trans
2346+
2347+
/-- Given a position in `s` that is between `p₀` and `p₁`, obtain the corresponding position in
2348+
`s.slice p₀ p₁ h`. -/
2349+
@[inline]
2350+
def Slice.Pos.slice {s : Slice} (pos : s.Pos) (p₀ p₁ : s.Pos) (h₁ : p₀ ≤ pos) (h₂ : pos ≤ p₁) :
2351+
(s.slice p₀ p₁ (Slice.Pos.le_trans h₁ h₂)).Pos where
2352+
offset := pos.offset.unoffsetBy p₀.offset
2353+
isValidForSlice := (Pos.Raw.isValidForSlice_slice _).2
2354+
(by simp [Pos.Raw.offsetBy_unoffsetBy_of_le h₁, Slice.Pos.le_iff.1 h₂, pos.isValidForSlice])
2355+
2356+
/-- Given a position in `s` that is between `p₀` and `p₁`, obtain the corresponding position in
2357+
`s.slice p₀ p₁ h`. -/
2358+
@[inline]
2359+
def Pos.slice {s : String} (pos : s.Pos) (p₀ p₁ : s.Pos) (h₁ : p₀ ≤ pos) (h₂ : pos ≤ p₁) :
2360+
(s.slice p₀ p₁ (Pos.le_trans h₁ h₂)).Pos :=
2361+
Slice.Pos.slice pos.toSlice _ _ h₁ h₂
2362+
2363+
@[simp]
2364+
theorem Pos.offset_slice {s : String} {p₀ p₁ pos : s.Pos} {h₁ : p₀ ≤ pos} {h₂ : pos ≤ p₁} :
2365+
(pos.slice p₀ p₁ h₁ h₂).offset = pos.offset.unoffsetBy p₀.offset := (rfl)
2366+
2367+
/--
2368+
Given a position in `s`, obtain the corresponding position in `s.slice p₀ p₁ h`, or panic if `pos`
2369+
is not between `p₀` and `p₁`.
2370+
-/
2371+
@[inline]
2372+
def Slice.Pos.sliceOrPanic {s : Slice} (pos : s.Pos) (p₀ p₁ : s.Pos) {h} :
2373+
(s.slice p₀ p₁ h).Pos :=
2374+
if h : p₀ ≤ pos ∧ pos ≤ p₁ then
2375+
pos.slice p₀ p₁ h.1 h.2
2376+
else
2377+
panic! "Position is outside of the bounds of the slice."
2378+
2379+
/--
2380+
Given a position in `s`, obtain the corresponding position in `s.slice p₀ p₁ h`, or panic if `pos`
2381+
is not between `p₀` and `p₁`.
2382+
-/
2383+
@[inline]
2384+
def Pos.sliceOrPanic {s : String} (pos : s.Pos) (p₀ p₁ : s.Pos) {h} :
2385+
(s.slice p₀ p₁ h).Pos :=
2386+
Slice.Pos.sliceOrPanic pos.toSlice _ _
2387+
2388+
theorem Slice.slice_eq_slice! {s : Slice} {p₀ p₁ h} : s.slice p₀ p₁ h = s.slice! p₀ p₁ := by
2389+
simp [slice!, h]
2390+
2391+
theorem slice_eq_slice! {s : String} {p₀ p₁ h} : s.slice p₀ p₁ h = s.slice! p₀ p₁ := by
2392+
simp [slice!, slice, Slice.slice_eq_slice!]
2393+
2394+
/-- Given a position in `s.slice! p₀ p₁`, obtain the corresponding position in `s`, or panic if
2395+
taking `s.slice! p₀ p₁` already panicked. -/
2396+
@[inline]
2397+
def Slice.Pos.ofSlice! {s : Slice} {p₀ p₁ : s.Pos} (pos : (s.slice! p₀ p₁).Pos) : s.Pos :=
2398+
if h : p₀ ≤ p₁ then
2399+
ofSlice (h := h) (pos.cast slice_eq_slice!.symm)
2400+
else
2401+
panic! "Starting position must be less than or equal to end position."
2402+
2403+
/-- Given a position in `s.slice! p₀ p₁`, obtain the corresponding position in `s`, or panic if
2404+
taking `s.slice! p₀ p₁` already panicked. -/
2405+
@[inline]
2406+
def Pos.ofSlice! {s : String} {p₀ p₁ : s.Pos} (pos : (s.slice! p₀ p₁).Pos) : s.Pos :=
2407+
ofToSlice (Slice.Pos.ofSlice! pos)
2408+
2409+
/--
2410+
Given a position in `s`, obtain the corresponding position in `s.slice! p₀ p₁ h`, or panic if
2411+
taking `s.slice! p₀ p₁` already panicked or if the position is not between `p₀` and `p₁`.
2412+
-/
2413+
@[inline]
2414+
def Slice.Pos.slice! {s : Slice} (pos : s.Pos) (p₀ p₁ : s.Pos) :
2415+
(s.slice! p₀ p₁).Pos :=
2416+
if h : p₀ ≤ pos ∧ pos ≤ p₁ then
2417+
(pos.slice _ _ h.1 h.2).cast slice_eq_slice!
2418+
else
2419+
panic! "Starting position must be less than or equal to end position and position must be between starting position and end position."
2420+
2421+
/--
2422+
Given a position in `s`, obtain the corresponding position in `s.slice! p₀ p₁ h`, or panic if
2423+
taking `s.slice! p₀ p₁` already panicked or if the position is not between `p₀` and `p₁`.
2424+
-/
2425+
@[inline]
2426+
def Pos.slice! {s : String} (pos : s.Pos) (p₀ p₁ : s.Pos) :
2427+
(s.slice! p₀ p₁).Pos :=
2428+
Slice.Pos.slice! pos.toSlice _ _
2429+
23142430
/--
23152431
Advances the position `p` `n` times.
23162432
@@ -2346,7 +2462,7 @@ If this would move `p` past the end of `s`, the result is `s.endPos`.
23462462
-/
23472463
@[inline]
23482464
def Pos.nextn {s : String} (p : s.Pos) (n : Nat) : s.Pos :=
2349-
(p.toSlice.nextn n).ofSlice
2465+
ofToSlice (p.toSlice.nextn n)
23502466

23512467
/--
23522468
Iterates `p.prev` `n` times.
@@ -2355,7 +2471,7 @@ If this would move `p` past the start of `s`, the result is `s.startPos`.
23552471
-/
23562472
@[inline]
23572473
def Pos.prevn {s : String} (p : s.Pos) (n : Nat) : s.Pos :=
2358-
(p.toSlice.prevn n).ofSlice
2474+
ofToSlice (p.toSlice.prevn n)
23592475

23602476
theorem Slice.Pos.le_nextn {s : Slice} {p : s.Pos} {n : Nat} : p ≤ p.nextn n := by
23612477
fun_induction nextn with

0 commit comments

Comments
 (0)