| /- | |
| Copyright (c) 2021 Microsoft Corporation. All rights reserved. | |
| Released under Apache 2.0 license as described in the file LICENSE. | |
| Authors: Leonardo de Moura | |
| -/ | |
| prelude | |
| import Lean.ScopedEnvExtension | |
| import Lean.Util.Recognizers | |
| import Lean.Util.ReplaceExpr | |
| namespace Lean.Compiler | |
| namespace CSimp | |
| structure Entry where | |
| fromDeclName : Name | |
| toDeclName : Name | |
| thmName : Name | |
| deriving Inhabited | |
| structure State where | |
| map : SMap Name Name := {} | |
| thmNames : SSet Name := {} | |
| deriving Inhabited | |
| def State.switch : State → State | |
| | { map, thmNames } => { map := map.switch, thmNames := thmNames.switch } | |
| builtin_initialize ext : SimpleScopedEnvExtension Entry State ← | |
| registerSimpleScopedEnvExtension { | |
| initial := {} | |
| addEntry := fun { map, thmNames } { fromDeclName, toDeclName, thmName } => { map := map.insert fromDeclName toDeclName, thmNames := thmNames.insert thmName } | |
| finalizeImport := fun s => s.switch | |
| } | |
| private def isConstantReplacement? (declName : Name) : CoreM (Option Entry) := do | |
| let info ← getConstInfo declName | |
| match info.type.eq? with | |
| | some (_, Expr.const fromDeclName us .., Expr.const toDeclName vs ..) => | |
| if us == vs then | |
| return some { fromDeclName, toDeclName, thmName := declName } | |
| else | |
| return none | |
| | _ => return none | |
| def add (declName : Name) (kind : AttributeKind) : CoreM Unit := do | |
| if let some entry ← isConstantReplacement? declName then | |
| ext.add entry kind | |
| else | |
| throwError "invalid 'csimp' theorem, only constant replacement theorems (e.g., `@f = @g`) are currently supported." | |
| builtin_initialize | |
| registerBuiltinAttribute { | |
| name := `csimp | |
| descr := "simplification theorem for the compiler" | |
| add := fun declName stx attrKind => do | |
| Attribute.Builtin.ensureNoArgs stx | |
| discard <| add declName attrKind | |
| } | |
| @[export lean_csimp_replace_constants] | |
| def replaceConstants (env : Environment) (e : Expr) : Expr := | |
| let s := ext.getState env | |
| e.replace fun e => | |
| if e.isConst then | |
| match s.map.find? e.constName! with | |
| | some declNameNew => some (mkConst declNameNew e.constLevels!) | |
| | none => none | |
| else | |
| none | |
| end CSimp | |
| def hasCSimpAttribute (env : Environment) (declName : Name) : Bool := | |
| CSimp.ext.getState env |>.thmNames.contains declName | |
| end Lean.Compiler |