lean4-htt/library/init/meta/fun_info.lean
2017-02-17 10:21:06 -08:00

129 lines
4.3 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.tactic init.meta.format init.function
structure param_info :=
(is_implicit : bool)
(is_inst_implicit : bool)
(is_prop : bool)
(has_fwd_deps : bool)
(back_deps : list nat) -- previous parameters it depends on
open format list decidable
private meta def ppfield {α : Type} [has_to_format α] (fname : string) (v : α) : format :=
group $ to_fmt fname ++ space ++ to_fmt ":=" ++ space ++ nest (length fname + 4) (to_fmt v)
private meta def concat_fields (f₁ f₂ : format) : format :=
if is_nil f₁ then f₂
else if is_nil f₂ then f₁
else f₁ ++ to_fmt "," ++ line ++ f₂
local infix `+++`:65 := concat_fields
meta def param_info.to_format : param_info → format
| (param_info.mk i ii p d ds) :=
group ∘ cbrace $
when i "implicit" +++
when ii "inst_implicit" +++
when p "prop" +++
when d "has_fwd_deps" +++
when (length ds > 0) (to_fmt "back_deps := " ++ to_fmt ds)
meta instance : has_to_format param_info :=
has_to_format.mk param_info.to_format
structure fun_info :=
(params : list param_info)
(result_deps : list nat) -- parameters the result type depends on
meta def fun_info_to_format : fun_info → format
| (fun_info.mk ps ds) :=
group ∘ dcbrace $
ppfield "params" ps +++
ppfield "result_deps" ds
meta instance : has_to_format fun_info :=
has_to_format.mk fun_info_to_format
/-
specialized is true if the result of fun_info has been specifialized
using this argument.
For example, consider the function
f : Pi (α : Type), α -> α
Now, suppse we request get_specialize fun_info for the application
f unit a
fun_info_manager returns two param_info objects:
1) specialized = true
2) is_subsingleton = true
Note that, in general, the second argument of f is not a subsingleton,
but it is in this particular case/specialization.
\remark This bit is only set if it is a dependent parameter.
Moreover, we only set is_specialized IF another parameter
becomes a subsingleton -/
structure subsingleton_info :=
(specialized : bool)
(is_subsingleton : bool)
meta def subsingleton_info_to_format : subsingleton_info → format
| (subsingleton_info.mk s ss) :=
group ∘ cbrace $
when s "specialized" +++
when ss "subsingleton"
meta instance : has_to_format subsingleton_info :=
has_to_format.mk subsingleton_info_to_format
namespace tactic
/-- If nargs is not none, then return information assuming the function has only nargs arguments. -/
meta constant get_fun_info (f : expr) (nargs : option nat := none) (md := semireducible) : tactic fun_info
meta constant get_subsingleton_info (f : expr) (nargs : option nat := none) (md := semireducible) : tactic (list subsingleton_info)
/- (get_spec_subsingleton_info t) return subsingleton parameter
information for the function application t of the form
(f a_1 ... a_n).
This tactic is more precise than (get_subsingleton_info f) and (get_subsingleton_info_n f n)
Example: given (f : Pi (α : Type), α -> α), \c get_spec_subsingleton_info for
f unit b
returns a fun_info with two param_info
1) specialized = tt
2) is_subsingleton = tt
The second argument is marked as subsingleton only because the resulting information
is taking into account the first argument. -/
meta constant get_spec_subsingleton_info (t : expr) (md := semireducible) : tactic (list subsingleton_info)
meta constant get_spec_prefix_size (t : expr) (nargs : nat) (md := semireducible) : tactic nat
private meta def is_next_explicit : list param_info → bool
| [] := tt
| (p::ps) := bnot p^.is_implicit && bnot p^.is_inst_implicit
meta def fold_explicit_args_aux {α} (f : α → expr → tactic α) : list expr → list param_info → α → tactic α
| [] _ a := return a
| (e::es) ps a :=
if is_next_explicit ps
then f a e >>= fold_explicit_args_aux es ps^.tail
else fold_explicit_args_aux es ps^.tail a
meta def fold_explicit_args {α} (e : expr) (a : α) (f : α → expr → tactic α) : tactic α :=
if e^.is_app then do
info ← get_fun_info e^.get_app_fn (some e^.get_app_num_args),
fold_explicit_args_aux f e^.get_app_args info^.params a
else return a
end tactic