/- Copyright (c) 2020 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Author: Leonardo de Moura -/ import Lean.Data.Occurrences import Lean.HeadIndex import Lean.Meta.ExprDefEq namespace Lean namespace Meta private partial def kabstractAux (occs : Occurrences) (p : Expr) (pHeadIdx : HeadIndex) (pNumArgs : Nat) : Expr → Nat → StateT Nat MetaM Expr | e, offset => let visitChildren : Unit → StateT Nat MetaM Expr := fun _ => match e with | Expr.app f a _ => do f ← kabstractAux f offset; a ← kabstractAux a offset; pure $ e.updateApp! f a | Expr.mdata _ b _ => do b ← kabstractAux b offset; pure $ e.updateMData! b | Expr.proj _ _ b _ => do b ← kabstractAux b offset; pure $ e.updateProj! b | Expr.letE _ t v b _ => do t ← kabstractAux t offset; v ← kabstractAux v offset; b ← kabstractAux b (offset+1); pure $ e.updateLet! t v b | Expr.lam _ d b _ => do d ← kabstractAux d offset; b ← kabstractAux b (offset+1); pure $ e.updateLambdaE! d b | Expr.forallE _ d b _ => do d ← kabstractAux d offset; b ← kabstractAux b (offset+1); pure $ e.updateForallE! d b | e => pure e; if e.hasLooseBVars then visitChildren () else if e.toHeadIndex == pHeadIdx && e.headNumArgs == pNumArgs then condM (liftM $ isDefEq e p) (do i ← get; set (i+1); if occs.contains i then pure (mkBVar offset) else visitChildren ()) (visitChildren ()) else visitChildren () def kabstract (e : Expr) (p : Expr) (occs : Occurrences := Occurrences.all) : MetaM Expr := (kabstractAux occs p p.toHeadIndex p.headNumArgs e 0).run' 1 end Meta end Lean