Skip to content

Commit d856808

Browse files
authored
Lean 4 backend: further function implementation (2) (#4827)
This PR implements the following functions in the Lean 4 backend prelude: - `modInt` - `>=Int` - `Bytes2Int` - `Bytes.substr` Due to implementing `Bytes2Int` the PR also adds `SortSignedness` to the prelude, excluding it from the automatic generation.
1 parent b69c38e commit d856808

2 files changed

Lines changed: 49 additions & 2 deletions

File tree

  • pyk/src/pyk/klean

pyk/src/pyk/klean/k2lean4.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,25 +59,30 @@
5959
'SortString',
6060
'SortStringBuffer',
6161
'SortEndianness',
62+
'SortSignedness',
6263
}
6364
_PRELUDE_FUNCS: Final = {
6465
"Lbl'UndsPlus'Int'Unds'", # +Int
6566
"Lbl'Unds'-Int'Unds'", # -Int
6667
"Lbl'UndsStar'Int'Unds'", # *Int
6768
"Lbl'UndsSlsh'Int'Unds'", # /Int
69+
"Lbl'Unds'modInt'Unds'", # modInt
6870
"LblmaxInt'LParUndsCommUndsRParUnds'INT-COMMON'Unds'Int'Unds'Int'Unds'Int", # maxInt
6971
"Lbl'Tild'Int'Unds'", # ~Int
7072
"Lbl'Unds-LT-Eqls'Int'Unds'", # <=Int
73+
"Lbl'Unds-GT-Eqls'Int'Unds'", # >=Int
7174
"Lbl'Unds-LT-'Int'Unds'", # <Int
7275
"Lbl'Unds-GT-'Int'Unds'", # >Int
7376
"Lbl'UndsEqlsEqls'Int'Unds'", # ==Int
7477
"Lbl'Stop'Bytes'Unds'BYTES-HOOKED'Unds'Bytes", # Bytes.empty
7578
"Lbllog2Int'LParUndsRParUnds'INT-COMMON'Unds'Int'Unds'Int", # Int.log2
7679
"LblInt2Bytes'LParUndsCommUndsCommUndsRParUnds'BYTES-HOOKED'Unds'Bytes'Unds'Int'Unds'Int'Unds'Endianness", # Int2Bytes
80+
"LblBytes2Int'LParUndsCommUndsCommUndsRParUnds'BYTES-HOOKED'Unds'Int'Unds'Bytes'Unds'Endianness'Unds'Signedness", # Bytes2Int
7781
"LblpadRightBytes'LParUndsCommUndsCommUndsRParUnds'BYTES-HOOKED'Unds'Bytes'Unds'Bytes'Unds'Int'Unds'Int", # padRight
7882
"LblpadLeftBytes'LParUndsCommUndsCommUndsRParUnds'BYTES-HOOKED'Unds'Bytes'Unds'Bytes'Unds'Int'Unds'Int", # padLeft
7983
"LbllengthBytes'LParUndsRParUnds'BYTES-HOOKED'Unds'Int'Unds'Bytes", # Bytes.length
8084
"LblreplaceAtBytes'LParUndsCommUndsCommUndsRParUnds'BYTES-HOOKED'Unds'Bytes'Unds'Bytes'Unds'Int'Unds'Bytes", # Bytes.replaceAt
85+
"LblsubstrBytes'LParUndsCommUndsCommUndsRParUnds'BYTES-HOOKED'Unds'Bytes'Unds'Bytes'Unds'Int'Unds'Int", # Bytes.substr
8186
}
8287

8388
_SYMBOL_OVERRIDES: Final = {

pyk/src/pyk/klean/template/{{ cookiecutter.package_name }}/{{ cookiecutter.library_name }}/Prelude.lean

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -240,15 +240,18 @@ def «_+Int_» (x0 x1 : SortInt) : Option SortInt := some (x0 + x1)
240240
def «_-Int_» (x0 x1 : SortInt) : Option SortInt := some (x0 - x1)
241241
def «_*Int_» (x0 x1 : SortInt) : Option SortInt := some (x0 * x1)
242242
def «_/Int_» (x0 x1 : SortInt) : Option SortInt :=
243-
if x1 == 0 then none else some (Int.tdiv x0 x1)
243+
ite (x1 == 0) none (Int.tdiv x0 x1)
244+
def _modInt_ (x0 : SortInt) (x1 : SortInt) : Option SortInt :=
245+
ite (x1 == 0) none (Int.emod x0 x1)
244246
def «maxInt(_,_)_INT-COMMON_Int_Int_Int» (x0 x1 : SortInt) :=
245247
some (ite (x0 < x1) x1 x0)
246248
def «log2Int(_)_INT-COMMON_Int_Int» (x0 : SortInt) : Option SortInt :=
247-
ite (0 < x0) (some (Nat.log2 x0.toNat)) none
249+
ite (0 < x0) ((Nat.log2 x0.toNat) : Int) none
248250
def «~Int_» (x0 : SortInt) : Option SortInt := some (.not x0)
249251

250252
-- Comparisons
251253
def «_<=Int_» (x0 x1 : SortInt) : Option SortBool := some (x0 <= x1)
254+
def «_>=Int_» (x0 x1 : SortInt) : Option SortBool := some (x0 >= x1)
252255
def «_<Int_» (x0 x1 : SortInt) : Option SortBool := some (x0 < x1)
253256
def «_>Int_» (x0 x1 : SortInt) : Option SortBool := some (x0 > x1)
254257
def «_==Int_» (x0 x1 : SortInt) : Option SortBool := some (x0 == x1)
@@ -260,6 +263,11 @@ inductive SortEndianness : Type where
260263
| littleEndianBytes : SortEndianness
261264
deriving BEq, DecidableEq
262265

266+
inductive SortSignedness : Type where
267+
| signedBytes : SortSignedness
268+
| unsignedBytes : SortSignedness
269+
deriving BEq, DecidableEq
270+
263271
def «.Bytes_BYTES-HOOKED_Bytes» : Option SortBytes := some .empty
264272

265273
-- Adapted from https://github.com/runtimeverification/haskell-backend/blob/362dab30d6435ec117862fea722be67373572034/kore/src/Kore/Builtin/InternalBytes.hs#L496-L511
@@ -277,6 +285,31 @@ def «Int2Bytes(_,_,_)_BYTES-HOOKED_Bytes_Int_Int_Endianness» (x0 x1 : SortInt)
277285
| .succ l, n => ⟨(n % 256).toNat⟩ :: bytes l (n / 256)
278286
bytes x0.toNat x1
279287

288+
-- Adapted from
289+
-- https://github.com/runtimeverification/haskell-backend/blob/362dab30d6435ec117862fea722be67373572034/kore/src/Kore/Builtin/InternalBytes.hs#L527-L543
290+
-- Note that we use `List.foldl` and not `ByteArray.foldl` for ease of reasoning
291+
def «Bytes2Int(_,_,_)_BYTES-HOOKED_Int_Bytes_Endianness_Signedness» (bytes : SortBytes) (endian : SortEndianness) (sign : SortSignedness) : Option SortInt :=
292+
match sign with
293+
| .unsignedBytes => Int.ofNat unsigned
294+
| .signedBytes => if 2 * unsigned >= modulus then (Int.ofNat unsigned) - (Int.ofNat modulus)
295+
else Int.ofNat unsigned
296+
where
297+
modulus : Nat := res.1
298+
unsigned : Nat := res.2
299+
res : Nat×Nat :=
300+
let littleEndian := match endian with
301+
| .littleEndianBytes => bytes.toList
302+
--match bytes with |⟨⟨l⟩⟩ => l
303+
| .bigEndianBytes => bytes.toList.reverse
304+
--match bytes with |⟨⟨l⟩⟩ => l.reverse
305+
let go (res : Nat×Nat) (b : UInt8) : Nat×Nat :=
306+
-- `place` is `res.1`
307+
-- `acc` is `res.2`
308+
let place := res.1 * 0x100
309+
let acc := res.2 + res.1 * b.toNat
310+
⟨place, acc⟩
311+
List.foldl go (1, 0) littleEndian
312+
280313
/--
281314
Pads to the right `len - b.length` bytes with specified `val` value
282315
-/
@@ -304,3 +337,12 @@ def «replaceAtBytes(_,_,_)_BYTES-HOOKED_Bytes_Bytes_Int_Bytes» (dest : SortByt
304337
let init := dest.data.extract 0 index.toNat
305338
let rem := dest.data.extract (index.toNat + src.size) dest.size
306339
some { data := init ++ src.data ++ rem }
340+
341+
/--
342+
Get a new `Bytes` object containing a range of bytes from the input `Bytes`
343+
-/
344+
def «substrBytes(_,_,_)_BYTES-HOOKED_Bytes_Bytes_Int_Int» (b : SortBytes) (startIndex : SortInt) (endIndex : SortInt) : Option SortBytes :=
345+
if startIndex < 0 then none else
346+
if endIndex < startIndex then none else
347+
if b.size < endIndex then none else
348+
b.extract startIndex.toNat endIndex.toNat

0 commit comments

Comments
 (0)