Skip to content

Commit 5fb25ff

Browse files
authored
feat: grind instances for String.Pos and variants (#11384)
This PR adds the necessary instances for `grind` to reason about `String.Pos.Raw`, `String.Pos` and `String.Slice.Pos`.
1 parent e8da78a commit 5fb25ff

File tree

3 files changed

+126
-0
lines changed

3 files changed

+126
-0
lines changed

src/Init/Data/String.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,4 @@ public import Init.Data.String.Termination
2525
public import Init.Data.String.ToSlice
2626
public import Init.Data.String.Search
2727
public import Init.Data.String.Legacy
28+
public import Init.Data.String.Grind

src/Init/Data/String/Grind.lean

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
/-
2+
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Author: Markus Himmel
5+
-/
6+
module
7+
8+
prelude
9+
public import Init.Data.String.Defs
10+
public import Init.Grind.ToInt
11+
12+
public section
13+
14+
/-!
15+
# Register string positions with `grind`.
16+
-/
17+
18+
namespace String
19+
20+
namespace Internal
21+
22+
scoped macro "order" : tactic => `(tactic| {
23+
simp [Pos.Raw.lt_iff, Pos.Raw.le_iff, String.Pos.lt_iff, String.Pos.le_iff, Slice.Pos.lt_iff,
24+
Slice.Pos.le_iff, Pos.Raw.ext_iff, String.Pos.ext_iff, Slice.Pos.ext_iff] at *;
25+
try omega })
26+
27+
end Internal
28+
29+
open Internal
30+
31+
namespace Pos.Raw
32+
33+
instance : Lean.Grind.ToInt String.Pos.Raw (.ci 0) where
34+
toInt p := p.byteIdx
35+
toInt_inj p q := by simp [Pos.Raw.ext_iff, ← Int.ofNat_inj]
36+
toInt_mem := by simp
37+
38+
@[simp]
39+
theorem toInt_eq {p : Pos.Raw} : Lean.Grind.ToInt.toInt p = p.byteIdx := rfl
40+
41+
instance : Lean.Grind.ToInt.LE String.Pos.Raw (.ci 0) where
42+
le_iff := by simp [Pos.Raw.le_iff]
43+
44+
instance : Lean.Grind.ToInt.LT String.Pos.Raw (.ci 0) where
45+
lt_iff := by simp [Pos.Raw.lt_iff]
46+
47+
instance : Std.LawfulOrderLT String.Pos.Raw where
48+
lt_iff := by order
49+
50+
instance : Std.IsLinearOrder String.Pos.Raw where
51+
le_refl := by order
52+
le_trans := by order
53+
le_antisymm := by order
54+
le_total := by order
55+
56+
end Pos.Raw
57+
58+
namespace Pos
59+
60+
instance {s : String} : Lean.Grind.ToInt s.Pos (.co 0 (s.utf8ByteSize + 1)) where
61+
toInt p := p.offset.byteIdx
62+
toInt_inj p q := by simp [Pos.ext_iff, Pos.Raw.ext_iff, ← Int.ofNat_inj]
63+
toInt_mem p := by have := p.isValid.le_utf8ByteSize; simp; omega
64+
65+
@[simp]
66+
theorem toInt_eq {s : String} {p : s.Pos} : Lean.Grind.ToInt.toInt p = p.offset.byteIdx := rfl
67+
68+
instance {s : String} : Lean.Grind.ToInt.LE s.Pos (.co 0 (s.utf8ByteSize + 1)) where
69+
le_iff := by simp [Pos.le_iff, Pos.Raw.le_iff]
70+
71+
instance {s : String} : Lean.Grind.ToInt.LT s.Pos (.co 0 (s.utf8ByteSize + 1)) where
72+
lt_iff := by simp [Pos.lt_iff, Pos.Raw.lt_iff]
73+
74+
instance {s : String} : Std.LawfulOrderLT s.Pos where
75+
lt_iff := by order
76+
77+
instance {s : String} : Std.IsLinearOrder s.Pos where
78+
le_refl := by order
79+
le_trans := by order
80+
le_antisymm := by order
81+
le_total := by order
82+
83+
end Pos
84+
85+
namespace Slice.Pos
86+
87+
instance {s : Slice} : Lean.Grind.ToInt s.Pos (.co 0 (s.utf8ByteSize + 1)) where
88+
toInt p := p.offset.byteIdx
89+
toInt_inj p q := by simp [Pos.ext_iff, Pos.Raw.ext_iff, ← Int.ofNat_inj]
90+
toInt_mem p := by have := p.isValidForSlice.le_utf8ByteSize; simp; omega
91+
92+
@[simp]
93+
theorem toInt_eq {s : Slice} {p : s.Pos} : Lean.Grind.ToInt.toInt p = p.offset.byteIdx := rfl
94+
95+
instance {s : Slice} : Lean.Grind.ToInt.LE s.Pos (.co 0 (s.utf8ByteSize + 1)) where
96+
le_iff := by simp [Pos.le_iff, Pos.Raw.le_iff]
97+
98+
instance {s : Slice} : Lean.Grind.ToInt.LT s.Pos (.co 0 (s.utf8ByteSize + 1)) where
99+
lt_iff := by simp [Pos.lt_iff, Pos.Raw.lt_iff]
100+
101+
instance {s : Slice} : Std.LawfulOrderLT s.Pos where
102+
lt_iff := by order
103+
104+
instance {s : Slice} : Std.IsLinearOrder s.Pos where
105+
le_refl := by order
106+
le_trans := by order
107+
le_antisymm := by order
108+
le_total := by order
109+
110+
end Slice.Pos
111+
112+
end String
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
module
2+
3+
example {p q r : String.Pos.Raw} : p < q → q ≤ r → p < r := by
4+
lia
5+
6+
example {s : String} {p q r : s.Pos} : p < q → q ≤ r → p < r := by
7+
lia
8+
9+
example {s : String.Slice} {p q r : s.Pos} : p < q → q ≤ r → p < r := by
10+
lia
11+
12+
example {s : String} {p q : s.Pos} : p ≤ q ↔ p = q ∨ p < q := by
13+
lia

0 commit comments

Comments
 (0)