Skip to content

Commit 0f9008e

Browse files
fix: use correct bounds for oneOf and elements (#56)
The index of an array shouldn't go beyond its size-1. This patch also removes the use of `Array.get!` from `Gen.lean` and uses `Array` instead of `List` in `elements` because it does size computation and index-based access in O(1) at runtime. Further, it sets the `hi` value of the `DefaultRange` instance for `Nat` so that it's within the `USize` range, for guaranteed memory optimization at runtime.
1 parent 8ff5984 commit 0f9008e

File tree

3 files changed

+19
-17
lines changed

3 files changed

+19
-17
lines changed

LSpec/SlimCheck/Control/DefaultRange.lean

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,14 @@ instance : Bounded Bool where
4848

4949
instance : DefaultRange Nat where
5050
lo := 0
51-
hi := USize.size
51+
hi := USize.size - 1
5252

5353
instance {n : Nat} : Bounded (Fin n.succ) where
5454
lo := ⟨0, n.succ_pos⟩
5555
hi := ⟨n, n.lt_succ_self⟩
5656

5757
instance : DefaultRange Int where
58-
lo := - Int.ofNat (USize.size / 2)
58+
lo := - Int.ofNat (USize.size / 2)
5959
hi := Int.ofNat (USize.size / 2 - 1)
6060

6161
end SlimCheck

LSpec/SlimCheck/Gen.lean

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,6 @@ def chooseAny (α : Type u) [Random α] [DefaultRange α] : Gen α :=
3737
def choose (α : Type u) [Random α] (lo hi : α) : Gen α :=
3838
λ _ => randBound α lo hi
3939

40-
/-- Generate a `Nat` example between `x` and `y` (exclusively). -/
41-
def chooseNatLt (lo hi : Nat) : Gen Nat :=
42-
choose Nat (lo.succ) hi
43-
4440
/-- Get access to the size parameter of the `Gen` monad. -/
4541
def getSize : Gen Nat :=
4642
return (← read).down
@@ -63,17 +59,22 @@ by the size parameter of `Gen`. -/
6359
def listOf (x : Gen α) : Gen (List α) :=
6460
arrayOf x >>= pure ∘ Array.toList
6561

66-
/-- Given a list of example generators, choose one to create an example. -/
62+
/-- Given an array of example generators, choose one to create an example. -/
6763
def oneOf [Inhabited α] (xs : Array (Gen α)) : Gen α := do
68-
let x ← chooseNatLt 0 xs.size
69-
xs.get! x
70-
71-
/-- Given a list of examples, choose one to create an example. -/
72-
def elements [Inhabited α] (xs : List α) : Gen α := do
73-
let x ← chooseNatLt 0 xs.length
74-
pure $ xs.get! x
64+
let i ← choose Nat 0 (xs.size - 1)
65+
if h : i < xs.size then
66+
xs.get i h
67+
else -- The array is empty
68+
pure default
69+
70+
/-- Given an array of examples, choose one. -/
71+
def elements [Inhabited α] (xs : Array α) : Gen α := do
72+
let i ← choose Nat 0 (xs.size - 1)
73+
if h : i < xs.size then
74+
return xs.get i h
75+
else -- The array is empty
76+
pure default
7577

76-
open List in
7778
/-- Generate a random permutation of a given list. -/
7879
def permutationOf : (xs : List α) → Gen (List α)
7980
| [] => pure []

LSpec/SlimCheck/Sampleable.lean

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ instance Bool.sampleableExt : SampleableExt Bool :=
173173
/-- This can be specialized into customized `SampleableExt Char` instances.
174174
The resulting instance has `1 / length` chances of making an unrestricted choice of characters
175175
and it otherwise chooses a character from `chars` with uniform probabilities. -/
176-
def Char.sampleable (length : Nat) (chars : List Char) : SampleableExt Char :=
176+
def Char.sampleable (length : Nat) (chars : Array Char) : SampleableExt Char :=
177177
mkSelfContained do
178178
let x ← choose Nat 0 length
179179
if x == 0 then
@@ -183,7 +183,8 @@ def Char.sampleable (length : Nat) (chars : List Char) : SampleableExt Char :=
183183
elements chars
184184

185185
instance Char.sampleableDefault : SampleableExt Char :=
186-
Char.sampleable 3 " 0123abcABC:,;`\\/".toList
186+
Char.sampleable 3
187+
#[' ', '0', '1', '2', '3', 'a', 'b', 'c', 'A', 'B', 'C', ':', ',', ';', '`', '\\', '/']
187188

188189
instance Prod.sampleableExt {α β : Type u} [SampleableExt α] [SampleableExt β] :
189190
SampleableExt (α × β) where

0 commit comments

Comments
 (0)