feat: add helper functions for recognizing builtin literals
This commit is contained in:
parent
a3596d953d
commit
335fef4396
4 changed files with 129 additions and 0 deletions
|
|
@ -46,3 +46,4 @@ import Lean.Meta.Eval
|
|||
import Lean.Meta.CoeAttr
|
||||
import Lean.Meta.Iterator
|
||||
import Lean.Meta.LazyDiscrTree
|
||||
import Lean.Meta.LitValues
|
||||
|
|
|
|||
102
src/Lean/Meta/LitValues.lean
Normal file
102
src/Lean/Meta/LitValues.lean
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
/-
|
||||
Copyright (c) 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
Authors: Leonardo de Moura
|
||||
-/
|
||||
prelude
|
||||
import Lean.Meta.Basic
|
||||
|
||||
namespace Lean.Meta
|
||||
|
||||
/-!
|
||||
Helper functions for recognizing builtin literal values.
|
||||
This module focus on recognizing the standard representation used in Lean for these literals.
|
||||
It also provides support for the following exceptional cases.
|
||||
- Raw natural numbers (i.e., natural numbers which are not encoded using `OfNat.ofNat`).
|
||||
- Bit-vectors encoded using `OfNat.ofNat` and `BitVec.ofNat`.
|
||||
- Negative integers encoded using raw natural numbers.
|
||||
- Characters encoded `Char.ofNat n` where `n` can be a raw natural number or an `OfNat.ofNat`.
|
||||
-/
|
||||
|
||||
/-- Returns `some n` if `e` is a raw natural number, i.e., it is of the form `.lit (.natVal n)`. -/
|
||||
def getRawNatValue? (e : Expr) : Option Nat :=
|
||||
match e with
|
||||
| .lit (.natVal n) => some n
|
||||
| _ => none
|
||||
|
||||
/-- Return `some (n, type)` if `e` is an `OfNat.ofNat`-application encoding `n` for a type with name `typeDeclName`. -/
|
||||
def getOfNatValue? (e : Expr) (typeDeclName : Name) : MetaM (Option (Nat × Expr)) := OptionT.run do
|
||||
guard <| e.isAppOfArity ``OfNat.ofNat 3
|
||||
let type ← whnfD e.appFn!.appFn!.appArg!
|
||||
guard <| type.getAppFn.isConstOf typeDeclName
|
||||
let .lit (.natVal n) := e.appFn!.appArg! | failure
|
||||
return (n, type)
|
||||
|
||||
/-- Return `some n` if `e` is a raw natural number or an `OfNat.ofNat`-application encoding `n`. -/
|
||||
def getNatValue? (e : Expr) : MetaM (Option Nat) := do
|
||||
if let some n := getRawNatValue? e then
|
||||
return some n
|
||||
let some (n, _) ← getOfNatValue? e ``Nat | return none
|
||||
return some n
|
||||
|
||||
/-- Return `some i` if `e` `OfNat.ofNat`-application encoding an integer, or `Neg.neg`-application of one. -/
|
||||
def getIntValue? (e : Expr) : MetaM (Option Int) := do
|
||||
if let some (n, _) ← getOfNatValue? e ``Int then
|
||||
return some n
|
||||
if e.isAppOfArity ``Neg.neg 3 then
|
||||
let some (n, _) ← getOfNatValue? e.appArg! ``Int | return none
|
||||
return some (-n)
|
||||
return none
|
||||
|
||||
/-- Return `some c` if `e` is a `Char.ofNat`-application encoding character `c`. -/
|
||||
def getCharValue? (e : Expr) : MetaM (Option Char) := OptionT.run do
|
||||
guard <| e.isAppOfArity ``Char.ofNat 1
|
||||
let n ← getNatValue? e.appArg!
|
||||
return Char.ofNat n
|
||||
|
||||
/-- Return `some s` if `e` is of the form `.lit (.strVal s)`. -/
|
||||
def getStringValue? (e : Expr) : (Option String) :=
|
||||
match e with
|
||||
| .lit (.strVal s) => some s
|
||||
| _ => none
|
||||
|
||||
/-- Return `some ⟨n, v⟩` if `e` is af `OfNat.ofNat` application encoding a `Fin n` with value `v` -/
|
||||
def getFinValue? (e : Expr) : MetaM (Option ((n : Nat) × Fin n)) := OptionT.run do
|
||||
let (v, type) ← getOfNatValue? e ``Fin
|
||||
let n ← getNatValue? (← whnfD type.appArg!)
|
||||
match n with
|
||||
| 0 => failure
|
||||
| m+1 => return ⟨m+1, Fin.ofNat v⟩
|
||||
|
||||
/-- Return `some ⟨n, v⟩` if `e` is af `OfNat.ofNat` application encoding a `BitVec n` with value `v` -/
|
||||
def getBitVecValue? (e : Expr) : MetaM (Option ((n : Nat) × BitVec n)) := OptionT.run do
|
||||
if e.isAppOfArity ``BitVec.ofNat 2 then
|
||||
let n ← getNatValue? e.appFn!.appArg!
|
||||
let v ← getNatValue? e.appArg!
|
||||
return ⟨n, BitVec.ofNat n v⟩
|
||||
let (v, type) ← getOfNatValue? e ``BitVec
|
||||
IO.println v
|
||||
let n ← getNatValue? (← whnfD type.appArg!)
|
||||
return ⟨n, BitVec.ofNat n v⟩
|
||||
|
||||
/-- Return `some n` if `e` is an `OfNat.ofNat`-application encoding the `UInt8` with value `n`. -/
|
||||
def getUInt8Value? (e : Expr) : MetaM (Option UInt8) := OptionT.run do
|
||||
let (n, _) ← getOfNatValue? e ``UInt8
|
||||
return UInt8.ofNat n
|
||||
|
||||
/-- Return `some n` if `e` is an `OfNat.ofNat`-application encoding the `UInt16` with value `n`. -/
|
||||
def getUInt16Value? (e : Expr) : MetaM (Option UInt16) := OptionT.run do
|
||||
let (n, _) ← getOfNatValue? e ``UInt16
|
||||
return UInt16.ofNat n
|
||||
|
||||
/-- Return `some n` if `e` is an `OfNat.ofNat`-application encoding the `UInt32` with value `n`. -/
|
||||
def getUInt32Value? (e : Expr) : MetaM (Option UInt32) := OptionT.run do
|
||||
let (n, _) ← getOfNatValue? e ``UInt32
|
||||
return UInt32.ofNat n
|
||||
|
||||
/-- Return `some n` if `e` is an `OfNat.ofNat`-application encoding the `UInt64` with value `n`. -/
|
||||
def getUInt64Value? (e : Expr) : MetaM (Option UInt64) := OptionT.run do
|
||||
let (n, _) ← getOfNatValue? e ``UInt64
|
||||
return UInt64.ofNat n
|
||||
|
||||
end Lean.Meta
|
||||
14
tests/lean/lit_values.lean
Normal file
14
tests/lean/lit_values.lean
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import Lean
|
||||
open Lean Meta
|
||||
run_meta IO.println (← getNatValue? (toExpr 2))
|
||||
run_meta IO.println (← getNatValue? (mkRawNatLit 2))
|
||||
run_meta IO.println (← getIntValue? (toExpr (2 : Int)))
|
||||
run_meta IO.println (← getIntValue? (toExpr (-2)))
|
||||
run_meta IO.println (← getCharValue? (toExpr 'a'))
|
||||
#eval getStringValue? (toExpr "hello")
|
||||
run_meta IO.println (← getFinValue? (toExpr (3 : Fin 5)))
|
||||
run_meta IO.println (← getBitVecValue? (toExpr (3 : BitVec 12)))
|
||||
run_meta IO.println (← getUInt8Value? (toExpr (2 : UInt8)))
|
||||
run_meta IO.println (← getUInt16Value? (toExpr (2 : UInt16)))
|
||||
run_meta IO.println (← getUInt32Value? (toExpr (2 : UInt32)))
|
||||
run_meta IO.println (← getUInt64Value? (toExpr (2 : UInt64)))
|
||||
12
tests/lean/lit_values.lean.expected.out
Normal file
12
tests/lean/lit_values.lean.expected.out
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
(some 2)
|
||||
(some 2)
|
||||
(some 2)
|
||||
(some -2)
|
||||
(some a)
|
||||
(some (⟨5, 3⟩))
|
||||
(some (⟨12, 0x003#12⟩))
|
||||
(some 2)
|
||||
(some 2)
|
||||
(some 2)
|
||||
(some 2)
|
||||
some "hello"
|
||||
Loading…
Add table
Reference in a new issue