Skip to content

Commit fc8f290

Browse files
authored
feat: support native literals of size unsigned integer types (#8409)
This PR adds support to LCNF for native UInt8/UInt16/UInt32/UInt64 literals.
1 parent 423b317 commit fc8f290

File tree

7 files changed

+42
-4
lines changed

7 files changed

+42
-4
lines changed

src/Lean/Compiler/IR/EmitC.lean

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -495,7 +495,10 @@ def emitNumLit (t : IRType) (v : Nat) : M Unit := do
495495
else
496496
emit "lean_cstr_to_nat(\""; emit v; emit "\")"
497497
else
498-
emit v
498+
if v < UInt32.size then
499+
emit v
500+
else
501+
emit v; emit "ULL"
499502

500503
def emitLit (z : VarId) (t : IRType) (v : LitVal) : M Unit := do
501504
emitLhs z;

src/Lean/Compiler/IR/ToIR.lean

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ def lowerLitValue (v : LCNF.LitValue) : LitVal :=
6767
match v with
6868
| .nat n => .num n
6969
| .str s => .str s
70+
| .uint8 v => .num (UInt8.toNat v)
71+
| .uint16 v => .num (UInt16.toNat v)
72+
| .uint32 v => .num (UInt32.toNat v)
73+
| .uint64 v => .num (UInt64.toNat v)
7074

7175
-- TODO: This should be cached.
7276
def lowerEnumToScalarType (name : Name) : M (Option IRType) := do

src/Lean/Compiler/LCNF/Basic.lean

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,20 @@ def Param.toExpr (p : Param) : Expr :=
3636
inductive LitValue where
3737
| nat (val : Nat)
3838
| str (val : String)
39-
-- TODO: add constructors for `Int`, `Float`, `UInt` ...
39+
| uint8 (val : UInt8)
40+
| uint16 (val : UInt16)
41+
| uint32 (val : UInt32)
42+
| uint64 (val : UInt64)
43+
-- TODO: add constructors for `Int`, `Float`, `USize` ...
4044
deriving Inhabited, BEq, Hashable
4145

4246
def LitValue.toExpr : LitValue → Expr
4347
| .nat v => .lit (.natVal v)
4448
| .str v => .lit (.strVal v)
49+
| .uint8 v => .app (.const ``UInt8.ofNat []) (.lit (.natVal (UInt8.toNat v)))
50+
| .uint16 v => .app (.const ``UInt16.ofNat []) (.lit (.natVal (UInt16.toNat v)))
51+
| .uint32 v => .app (.const ``UInt32.ofNat []) (.lit (.natVal (UInt32.toNat v)))
52+
| .uint64 v => .app (.const ``UInt64.ofNat []) (.lit (.natVal (UInt64.toNat v)))
4553

4654
inductive Arg where
4755
| erased

src/Lean/Compiler/LCNF/ElimDeadBranches.lean

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,10 @@ def ofLCNFLit : LCNF.LitValue → Value
174174
| .nat n => ofNat n
175175
-- TODO: We could make this much more precise but the payoff is questionable
176176
| .str .. => .top
177+
| .uint8 v => ofNat (UInt8.toNat v)
178+
| .uint16 v => ofNat (UInt16.toNat v)
179+
| .uint32 v => ofNat (UInt32.toNat v)
180+
| .uint64 v => ofNat (UInt64.toNat v)
177181

178182
partial def proj : Value → Nat → Value
179183
| .ctor _ vs , i => vs.getD i bot

src/Lean/Compiler/LCNF/InferType.lean

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,10 @@ def inferLitValueType (value : LitValue) : Expr :=
105105
match value with
106106
| .nat .. => mkConst ``Nat
107107
| .str .. => mkConst ``String
108+
| .uint8 .. => mkConst ``UInt8
109+
| .uint16 .. => mkConst ``UInt16
110+
| .uint32 .. => mkConst ``UInt32
111+
| .uint64 .. => mkConst ``UInt64
108112

109113
mutual
110114
partial def inferArgType (arg : Arg) : InferTypeM Expr :=

src/Lean/Compiler/LCNF/PrettyPrinter.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ def ppArgs (args : Array Arg) : M Format := do
5858

5959
def ppLitValue (lit : LitValue) : M Format := do
6060
match lit with
61-
| .nat v => return format v
61+
| .nat v | .uint8 v | .uint16 v | .uint32 v | .uint64 v => return format v
6262
| .str v => return format (repr v)
6363

6464
def ppLetValue (e : LetValue) : M Format := do

src/Lean/Compiler/LCNF/Simp/ConstantFold.lean

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,14 @@ def higherOrderLiteralFolders : List (Name × Folder) := [
308308
def Folder.mulShift [Literal α] [BEq α] (shiftLeft : Name) (pow2 : α → α) (log2 : α → α) : Folder :=
309309
Folder.first #[Folder.mulLhsShift shiftLeft pow2 log2, Folder.mulRhsShift shiftLeft pow2 log2]
310310

311+
/--
312+
Folder for ofNat operations on fixed-sized integer types.
313+
-/
314+
def Folder.ofNat (f : Nat → LitValue) (args : Array Arg): FolderM (Option LetValue) := do
315+
let #[.fvar fvarId] := args | return none
316+
let some value ← getNatLit fvarId | return none
317+
return some (.lit (f value))
318+
311319
/--
312320
All arithmetic folders.
313321
-/
@@ -355,6 +363,13 @@ def relationFolders : List (Name × Folder) := [
355363
(``Bool.decEq, Folder.mkBinaryDecisionProcedure String.decEq)
356364
]
357365

366+
def conversionFolders : List (Name × Folder) := [
367+
(``UInt8.ofNat, Folder.ofNat (fun v => .uint8 (UInt8.ofNat v))),
368+
(``UInt16.ofNat, Folder.ofNat (fun v => .uint16 (UInt16.ofNat v))),
369+
(``UInt32.ofNat, Folder.ofNat (fun v => .uint32 (UInt32.ofNat v))),
370+
(``UInt64.ofNat, Folder.ofNat (fun v => .uint64 (UInt64.ofNat v))),
371+
]
372+
358373
/--
359374
All string folders.
360375
-/
@@ -387,7 +402,7 @@ private def getFolder (declName : Name) : CoreM Folder := do
387402
ofExcept <| getFolderCore (← getEnv) (← getOptions) declName
388403

389404
def builtinFolders : SMap Name Folder :=
390-
(arithmeticFolders ++ relationFolders ++ higherOrderLiteralFolders ++ stringFolders).foldl (init := {}) fun s (declName, folder) =>
405+
(arithmeticFolders ++ relationFolders ++ conversionFolders ++ higherOrderLiteralFolders ++ stringFolders).foldl (init := {}) fun s (declName, folder) =>
391406
s.insert declName folder
392407

393408
structure FolderOleanEntry where

0 commit comments

Comments
 (0)