The `unsafe_change e` tactic is similar to the `change e` tactic, but it
does not check whether `e` is definitionally equal to the current
tactic. It is useful when implementing tactics such as:
```
meta def dunfold : list name → tactic unit :=
λ cs, target >>= dunfold_core transparency.instances default_max_steps cs >>= unsafe_change
```
The tactic `dunfold_core` guarantees that the resultant expression is
definitionally equal to the input one.
This was one of the performance problems at issue #1646.
Here are the runtimes for size 7 in the example described at issue #1646.
Before this commit:
tactic execution took 4.96s
elaboration of some_lifted_lets took 7.6s
type checking time of some_lifted_lets took 31.1ms (aka QED time)
total execution time: 12.785s
After this commit:
tactic execution took 3.78s
elaboration of some_lifted_lets took 5.71s
type checking time of some_lifted_lets took 35.2ms
total execution time: 10.693s
closes#1634
This commit also changes the semantic of `tactic.focus [tac_1, ..., tac_n]`.
It now fails if the number of goals is not `n`.
Before it would only fail if there were more tactics than goals.
@Armael: See tests/lean/run/handthen.lean for examples of the new notation.
@Armael: this commit implements the `introv` tactic.
The implementation uses an auxiliary `intros_dep` that introduces new
hypotheses with forward dependencies.
The `tactic.introv` tactic implemented at library/init/meta/tactic.lean
is the main implementation, but it is not nice for interactive use since
users would have to write
```
tactic.introv [`h1, `h2]
```
To make it more conveninent to use, we define another
```
meta def introv (ns : parse ident_*) : tactic unit :=
tactic.introv ns >> return ()
```
This one is in the namespace `tactic.interactive`, and
uses parser extensions. The argument `parse ident_*` instructs
the parser to parse 0 or more identifiers and create a term
of type `list name` containing these identifiers.
Motivation: see "Other goodies" section at
https://github.com/leanprover/lean/wiki/Refactoring-structures
We had to add a new transparency mode: Instances at type_context.
In this mode, instances and reducible definitions are considered
transparent.
The new mode is used in the defeq_canonizer, code generator,
and sizeof lemma generation at inductive_compiler.
We also use the new mode in the unfold tactics.
Abstracting let-exprs may produce type errors.
In the future we may consider another strategy for `abstract`.
First, we try to abstract the `let`, then if it fails, we expand.
Not sure if this is a good idea.