lean4-htt/library/init/meta/expr.lean
Leonardo de Moura 9e7e600ad7 feat(kernel): add expr.proj constructor
TODO: implement infer_proj and reduce_proj
2018-06-19 15:45:49 -07:00

352 lines
10 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/-
Copyright (c) 2016 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
prelude
import init.meta.level init.control.monad init.lean.expr
universes u v
structure pos :=
(line : nat)
(column : nat)
instance : decidable_eq pos
| ⟨l₁, c₁⟩ ⟨l₂, c₂⟩ := if h₁ : l₁ = l₂ then
if h₂ : c₁ = c₂ then is_true (eq.rec_on h₁ (eq.rec_on h₂ rfl))
else is_false (λ contra, pos.no_confusion contra (λ e₁ e₂, absurd e₂ h₂))
else is_false (λ contra, pos.no_confusion contra (λ e₁ e₂, absurd e₁ h₁))
meta instance : has_to_format pos :=
⟨λ ⟨l, c⟩, "⟨" ++ l ++ ", " ++ c ++ "⟩"⟩
inductive binder_info
| default | implicit | strict_implicit | inst_implicit | aux_decl
instance : has_repr binder_info :=
⟨λ bi, match bi with
| binder_info.default := "default"
| binder_info.implicit := "implicit"
| binder_info.strict_implicit := "strict_implicit"
| binder_info.inst_implicit := "inst_implicit"
| binder_info.aux_decl := "aux_decl"⟩
meta constant macro_def : Type
inductive literal
| nat_val (val : nat)
| str_val (val : string)
/-- Reflect a C++ expr object. The VM replaces it with the C++ implementation. -/
meta inductive expr
| bvar : nat → expr -- bound variables
| fvar : name → expr -- free variables
| sort : level → expr
| const : name → list level → expr
| mvar : name → name → expr → expr
| app : expr → expr → expr
| lam : name → binder_info → expr → expr → expr
| pi : name → binder_info → expr → expr → expr
| elet : name → expr → expr → expr → expr
| lit : literal → expr
| mdata : lean.kvmap → expr → expr
| proj : nat → expr → expr
| macro : macro_def → list expr → expr
| quote : bool → expr → expr
meta instance : inhabited expr :=
⟨expr.sort level.zero⟩
meta constant expr.macro_def_name (d : macro_def) : name
meta def expr.mk_bvar (n : nat) : expr :=
expr.bvar n
/- Expressions can be annotated using the annotation macro. -/
meta constant expr.is_annotation : expr → option (name × expr)
meta def expr.erase_annotations : expr → expr
| e :=
match e.is_annotation with
| some (_, a) := expr.erase_annotations a
| none := e
/-- Compares expressions, including binder names. -/
meta constant expr.has_decidable_eq : decidable_eq expr
attribute [instance] expr.has_decidable_eq
/-- Compares expressions while ignoring binder names. -/
meta constant expr.alpha_eqv : expr → expr → bool
notation a ` =ₐ `:50 b:50 := expr.alpha_eqv a b = bool.tt
protected meta constant expr.to_string : expr → string
meta instance : has_to_string (expr) := ⟨expr.to_string⟩
meta instance : has_to_format (expr) := ⟨λ e, e.to_string⟩
/- Coercion for letting users write (f a) instead of (expr.app f a) -/
meta instance : has_coe_to_fun (expr) :=
{ F := λ e, expr → expr, coe := λ e, expr.app e }
meta constant expr.hash : expr → nat
/-- Compares expressions, ignoring binder names, and sorting by hash. -/
meta constant expr.lt : expr → expr → bool
/-- Compares expressions, ignoring binder names. -/
meta constant expr.lex_lt : expr → expr → bool
meta constant expr.fold {α : Type} : expr → α → (expr → nat → αα) → α
/-- `has_var e` returns true iff e has free variables. -/
meta constant expr.has_bvar_idx : expr → nat → bool
/-- (reflected a) is a special opaque container for a closed `expr` representing `a`.
It can only be obtained via type class inference, which will use the representation
of `a` in the calling context. Local constants in the representation are replaced
by nested inference of `reflected` instances.
The quotation expression `(a) (outside of patterns) is equivalent to `reflect a`
and thus can be used as an explicit way of inferring an instance of `reflected a`. -/
@[class] meta def reflected {α : Sort u} : α → Type :=
λ _, expr
@[inline] meta def reflected.to_expr {α : Sort u} {a : α} : reflected a → expr :=
id
@[instance] protected meta constant expr.reflect (e : expr) : reflected e
@[instance] protected meta constant string.reflect (s : string) : reflected s
protected meta constant expr.subst : expr → expr → expr
@[inline] meta def reflected.subst {α : Sort v} {β : α → Sort u} {f : Π a : α, β a} {a : α} :
reflected f → reflected a → reflected (f a) :=
λ ef ea, match ef with
| (expr.lam _ _ _ _) := (expr.subst ef ea)
| _ := expr.app ef ea
attribute [irreducible] reflected reflected.subst reflected.to_expr
@[inline] meta instance {α : Sort u} (a : α) : has_coe (reflected a) expr :=
⟨reflected.to_expr⟩
protected meta def reflect {α : Sort u} (a : α) [h : reflected a] : reflected a := h
meta instance {α} (a : α) : has_to_format (reflected a) :=
⟨λ h, to_fmt h.to_expr⟩
namespace expr
open decidable
meta def expr.lt_prop (a b : expr) : Prop :=
expr.lt a b = tt
meta instance : decidable_rel expr.lt_prop :=
λ a b, bool.decidable_eq _ _
/-- Compares expressions, ignoring binder names, and sorting by hash. -/
meta instance : has_lt expr :=
⟨ expr.lt_prop ⟩
meta def mk_true : expr :=
const `true []
meta def mk_false : expr :=
const `false []
meta def is_bvar : expr → bool
| (bvar _) := tt
| _ := ff
meta def app_of_list : expr → list expr → expr
| f [] := f
| f (p::ps) := app_of_list (f p) ps
meta def is_app : expr → bool
| (app f a) := tt
| e := ff
meta def app_fn : expr → expr
| (app f a) := f
| a := a
meta def app_arg : expr → expr
| (app f a) := a
| a := a
meta def get_app_fn : expr → expr
| (app f a) := get_app_fn f
| a := a
meta def get_app_num_args : expr → nat
| (app f a) := get_app_num_args f + 1
| e := 0
meta def get_app_args_aux : list expr → expr → list expr
| r (app f a) := get_app_args_aux (a::r) f
| r e := r
meta def get_app_args : expr → list expr :=
get_app_args_aux []
meta def mk_app : expr → list expr → expr
| e [] := e
| e (x::xs) := mk_app (e x) xs
meta def ith_arg_aux : expr → nat → expr
| (app f a) 0 := a
| (app f a) (n+1) := ith_arg_aux f n
| e _ := e
meta def ith_arg (e : expr) (i : nat) : expr :=
ith_arg_aux e (get_app_num_args e - i - 1)
meta def const_name : expr → name
| (const n ls) := n
| e := name.anonymous
meta def is_constant : expr → bool
| (const n ls) := tt
| e := ff
meta def is_fvar : expr → bool
| (fvar n) := tt
| e := ff
meta def fvar_id : expr → name
| (fvar n) := n
| e := name.anonymous
meta def is_constant_of : expr → name → bool
| (const n₁ ls) n₂ := n₁ = n₂
| e n := ff
meta def is_app_of (e : expr) (n : name) : bool :=
is_constant_of (get_app_fn e) n
meta def is_napp_of (e : expr) (c : name) (n : nat) : bool :=
is_app_of e c ∧ get_app_num_args e = n
meta def is_false : expr → bool
| `(false) := tt
| _ := ff
meta def is_not : expr → option expr
| `(not %%a) := some a
| `(%%a → false) := some a
| e := none
meta def is_and : expr → option (expr × expr)
| `(and %%α %%β) := some (α, β)
| _ := none
meta def is_or : expr → option (expr × expr)
| `(or %%α %%β) := some (α, β)
| _ := none
meta def is_iff : expr → option (expr × expr)
| `((%%a : Prop) ↔ %%b) := some (a, b)
| _ := none
meta def is_eq : expr → option (expr × expr)
| `((%%a : %%_) = %%b) := some (a, b)
| _ := none
meta def is_ne : expr → option (expr × expr)
| `((%%a : %%_) ≠ %%b) := some (a, b)
| _ := none
meta def is_bin_arith_app (e : expr) (op : name) : option (expr × expr) :=
if is_napp_of e op 4
then some (app_arg (app_fn e), app_arg e)
else none
meta def is_lt (e : expr) : option (expr × expr) :=
is_bin_arith_app e ``has_lt.lt
meta def is_gt (e : expr) : option (expr × expr) :=
is_bin_arith_app e ``gt
meta def is_le (e : expr) : option (expr × expr) :=
is_bin_arith_app e ``has_le.le
meta def is_ge (e : expr) : option (expr × expr) :=
is_bin_arith_app e ``ge
meta def is_heq : expr → option (expr × expr × expr × expr)
| `(@heq %%α %%a %%β %%b) := some (α, a, β, b)
| _ := none
meta def is_lambda : expr → bool
| (lam _ _ _ _) := tt
| e := ff
meta def is_pi : expr → bool
| (pi _ _ _ _) := tt
| e := ff
meta def is_let : expr → bool
| (elet _ _ _ _) := tt
| e := ff
meta def binding_name : expr → name
| (pi n _ _ _) := n
| (lam n _ _ _) := n
| e := name.anonymous
meta def binding_info : expr → binder_info
| (pi _ bi _ _) := bi
| (lam _ bi _ _) := bi
| e := binder_info.default
meta def binding_domain : expr → expr
| (pi _ _ d _) := d
| (lam _ _ d _) := d
| e := e
meta def binding_body : expr → expr
| (pi _ _ _ b) := b
| (lam _ _ _ b) := b
| e := e
meta def is_macro : expr → bool
| (macro d a) := tt
| e := ff
meta def is_numeral : expr → bool
| `(@has_zero.zero %%α %%s) := tt
| `(@has_one.one %%α %%s) := tt
| `(@bit0 %%α %%s %%v) := is_numeral v
| `(@bit1 %%α %%s₁ %%s₂ %%v) := is_numeral v
| _ := ff
meta def imp (a b : expr) : expr :=
pi `_ binder_info.default a b
meta def extract_opt_auto_param : expr → expr
| `(@opt_param %%t _) := extract_opt_auto_param t
| `(@auto_param %%t _) := extract_opt_auto_param t
| e := e
open format
private meta def p := λ xs, paren (format.join (list.intersperse " " xs))
meta def to_raw_fmt : expr → format
| (bvar n) := p ["bvar", to_fmt n]
| (lit l) := "lit"
| (fvar n) := p ["fvar", to_fmt n]
| (sort l) := p ["sort", to_fmt l]
| (const n ls) := p ["const", to_fmt n, to_fmt ls]
| (mvar n m t) := p ["mvar", to_fmt n, to_fmt m, to_raw_fmt t]
| (app e f) := p ["app", to_raw_fmt e, to_raw_fmt f]
| (lam n bi e t) := p ["lam", to_fmt n, repr bi, to_raw_fmt e, to_raw_fmt t]
| (pi n bi e t) := p ["pi", to_fmt n, repr bi, to_raw_fmt e, to_raw_fmt t]
| (elet n g e f) := p ["elet", to_fmt n, to_raw_fmt g, to_raw_fmt e, to_raw_fmt f]
| (mdata d e) := p ["mdata", to_raw_fmt e]
| (proj idx e) := p ["proj", to_fmt idx, to_raw_fmt e]
| (macro d args) := sbracket (format.join (list.intersperse " " ("macro" :: to_fmt (macro_def_name d) :: args.map to_raw_fmt)))
| (quote b v) := p ["quote", to_fmt b, to_raw_fmt v]
meta def mfold {α : Type} {m : Type → Type} [monad m] (e : expr) (a : α) (fn : expr → nat → α → m α) : m α :=
fold e (return a) (λ e n a, a >>= fn e n)
end expr