88 lines
2.6 KiB
Text
88 lines
2.6 KiB
Text
/-
|
|
Copyright (c) 2020 Microsoft Corporation. All rights reserved.
|
|
Released under Apache 2.0 license as described in the file LICENSE.
|
|
Authors: Leonardo de Moura, Mario Carneiro
|
|
-/
|
|
module
|
|
|
|
prelude
|
|
public import Lean.Data.AssocList
|
|
public import Lean.Expr
|
|
public import Lean.LocalContext
|
|
public import Lean.Util.ReplaceExpr
|
|
|
|
public section
|
|
|
|
namespace Lean.Meta
|
|
/--
|
|
Some tactics substitute hypotheses with expressions.
|
|
We track these substitutions using `FVarSubst`.
|
|
It is just a mapping from the original FVarId (internal) name
|
|
to an expression. The free variables occurring in the expression must
|
|
be defined in the new goal. -/
|
|
structure FVarSubst where
|
|
map : AssocList FVarId Expr := {}
|
|
deriving Inhabited
|
|
|
|
namespace FVarSubst
|
|
|
|
def empty : FVarSubst := {}
|
|
|
|
def isEmpty (s : FVarSubst) : Bool :=
|
|
s.map.isEmpty
|
|
|
|
def contains (s : FVarSubst) (fvarId : FVarId) : Bool :=
|
|
s.map.contains fvarId
|
|
|
|
/-- Add entry `fvarId |-> v` to `s` if `s` does not contain an entry for `fvarId`. -/
|
|
def insert (s : FVarSubst) (fvarId : FVarId) (v : Expr) : FVarSubst :=
|
|
if s.contains fvarId then s
|
|
else
|
|
let map := s.map.mapVal fun e => e.replaceFVarId fvarId v;
|
|
{ map := map.insertNew fvarId v }
|
|
|
|
def erase (s : FVarSubst) (fvarId : FVarId) : FVarSubst :=
|
|
{ map := s.map.erase fvarId }
|
|
|
|
def find? (s : FVarSubst) (fvarId : FVarId) : Option Expr :=
|
|
s.map.find? fvarId
|
|
|
|
def get (s : FVarSubst) (fvarId : FVarId) : Expr :=
|
|
match s.map.find? fvarId with
|
|
| none => mkFVar fvarId -- it has not been replaced
|
|
| some v => v
|
|
|
|
/-- Given `e`, for each `(x => v)` in `s` replace `x` with `v` in `e` -/
|
|
def apply (s : FVarSubst) (e : Expr) : Expr :=
|
|
if s.map.isEmpty then e
|
|
else if !e.hasFVar then e
|
|
else e.replace fun e => match e with
|
|
| Expr.fvar fvarId => match s.map.find? fvarId with
|
|
| none => e
|
|
| some v => v
|
|
| _ => none
|
|
|
|
def domain (s : FVarSubst) : List FVarId :=
|
|
s.map.foldl (init := []) fun r k _ => k :: r
|
|
|
|
def any (p : FVarId → Expr → Bool) (s : FVarSubst) : Bool :=
|
|
s.map.any p
|
|
|
|
/--
|
|
Constructs a substitution consisting of `s` followed by `t`.
|
|
This satisfies `(s.append t).apply e = t.apply (s.apply e)`
|
|
-/
|
|
def append (s t : FVarSubst) : FVarSubst :=
|
|
s.1.foldl (fun s' k v => s'.insert k (t.apply v)) t
|
|
|
|
end FVarSubst
|
|
end Meta
|
|
|
|
def LocalDecl.applyFVarSubst (s : Meta.FVarSubst) : LocalDecl → LocalDecl
|
|
| LocalDecl.cdecl i id n t bi k => LocalDecl.cdecl i id n (s.apply t) bi k
|
|
| LocalDecl.ldecl i id n t v nd k => LocalDecl.ldecl i id n (s.apply t) (s.apply v) nd k
|
|
|
|
abbrev Expr.applyFVarSubst (s : Meta.FVarSubst) (e : Expr) : Expr :=
|
|
s.apply e
|
|
|
|
end Lean
|