Skip to content

Commit d447004

Browse files
committed
feat(lean): add support for shift-left
1 parent f8114a7 commit d447004

File tree

5 files changed

+38
-2
lines changed

5 files changed

+38
-2
lines changed

hax-lib/proof-libs/lean/Hax/Integers/Ops.lean

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,14 @@ class HaxShiftRight α β where
6161
-/
6262
shiftRight : α → β → RustM α
6363

64+
/--The notation typeclass for left shift that returns a RustM. It enables the
65+
notation `a <<<? b : RustM α` where `a : α` and `b : β`. -/
66+
class HaxShiftLeft α β where
67+
/-- `a <<<? b` computes the panicking left-shift of `a` by `b`. The meaning
68+
of this notation is type-dependent. It panics if `b` exceeds the size of `a`.
69+
-/
70+
shiftLeft : α → β → RustM α
71+
6472
/-- The notation typeclass for remainder. This enables the notation `a %? b :
6573
RustM α` where `a b : α`. -/
6674
class HaxRem α where
@@ -72,6 +80,7 @@ class HaxRem α where
7280
@[inherit_doc] infixl:65 " -? " => HaxSub.sub
7381
@[inherit_doc] infixl:70 " *? " => HaxMul.mul
7482
@[inherit_doc] infixl:75 " >>>? " => HaxShiftRight.shiftRight
83+
@[inherit_doc] infixl:75 " <<<? " => HaxShiftLeft.shiftLeft
7584
@[inherit_doc] infixl:70 " %? " => HaxRem.rem
7685
@[inherit_doc] infixl:70 " /? " => HaxDiv.div
7786

@@ -85,7 +94,8 @@ class UnSigned (α: Type)
8594
(Mul α),
8695
(Div α),
8796
(Mod α),
88-
(ShiftRight α)
97+
(ShiftRight α),
98+
(ShiftLeft α)
8999
where
90100
[deq : DecidableEq α]
91101
width : Nat
@@ -174,6 +184,12 @@ instance {α : Type} [UnSigned α]: HaxShiftRight α α where
174184
if (UnSigned.width α) ≤ (UnSigned.toNat y) then .fail .integerOverflow
175185
else pure (x >>> y)
176186

187+
/- Left shift on unsigned rust integers. Panics when shifting by more than the size -/
188+
instance {α : Type} [UnSigned α]: HaxShiftLeft α α where
189+
shiftLeft x y :=
190+
if (UnSigned.width α) ≤ (UnSigned.toNat y) then .fail .integerOverflow
191+
else pure (x <<< y)
192+
177193
/- Signed operations -/
178194
class Signed (α: Type)
179195
extends (LE α),
@@ -183,7 +199,8 @@ class Signed (α: Type)
183199
(Mul α),
184200
(Div α),
185201
(Mod α),
186-
(ShiftRight α) where
202+
(ShiftRight α),
203+
(ShiftLeft α) where
187204
[dec: DecidableEq α]
188205
width : Nat
189206
toBitVec : α → BitVec width
@@ -274,6 +291,15 @@ instance {α : Type} [Signed α] : HaxShiftRight α α where
274291
else
275292
.fail .integerOverflow
276293

294+
/- Left shifting on signed integers. Panics when shifting by a negative number,
295+
or when shifting by more than the size. -/
296+
instance {α : Type} [Signed α] : HaxShiftLeft α α where
297+
shiftLeft x y :=
298+
if 0 ≤ (Signed.toInt y) && (Signed.toInt y) < Int.ofNat (Signed.width α) then
299+
pure (x <<< y)
300+
else
301+
.fail .integerOverflow
302+
277303
/- Check that all operations are implemented -/
278304

279305
class Operations α where
@@ -283,6 +309,7 @@ class Operations α where
283309
[instHaxDiv: HaxDiv α]
284310
[instHaxRem: HaxRem α]
285311
[instHaxShiftRight: HaxShiftRight α α]
312+
[instHaxShiftLeft: HaxShiftLeft α α]
286313

287314
instance : Operations u8 where
288315
instance : Operations u16 where
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{"version": "1.1.0",
2+
"packagesDir": ".lake/packages",
3+
"packages": [],
4+
"name": "Hax",
5+
"lakeDir": ".lake"}

rust-engine/src/backends/lean.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ impl Printer for LeanPrinter {
115115
binops::rem,
116116
binops::div,
117117
binops::shr,
118+
binops::shl,
118119
binops::bitand,
119120
binops::bitxor,
120121
binops::logical_op_and,
@@ -572,6 +573,7 @@ set_option linter.unusedVariables false
572573
binops::div => "/?",
573574
binops::rem => "%?",
574575
binops::shr => ">>>?",
576+
binops::shl => "<<<?",
575577
binops::bitand => "&&&?",
576578
binops::bitxor => "^^^?",
577579
binops::logical_op_and => "&&?",

test-harness/src/snapshots/toolchain__lean-tests into-lean.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -730,6 +730,7 @@ def Lean_tests.binop_resugarings (x : u32) : RustM u32 := do
730730
let rem : u32 ← (mul %? (4 : u32));
731731
let div : u32 ← (rem /? (5 : u32));
732732
let rshift : u32 ← (div >>>? x);
733+
let lshift : u32 ← (div <<<? x);
733734
(pure x)
734735

735736
def Lean_tests.Reject_do_dsl.rejected

tests/lean-tests/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,5 +61,6 @@ fn binop_resugarings(x: u32) -> u32 {
6161
let rem = mul % 4;
6262
let div = rem / 5;
6363
let rshift = div >> x;
64+
let lshift = div << x;
6465
x
6566
}

0 commit comments

Comments
 (0)