Auxiliary elaboration functions: AKA custom elaborators #
The elaborator for binop%
, binop_lazy%
, and unop%
terms.
It works as follows:
1- Expand macros.
2- Convert Syntax
object corresponding to the binop%
(binop_lazy%
and unop%
) term into a Tree
.
The toTree
method visits nested binop%
(binop_lazy%
and unop%
) terms and parentheses.
3- Synthesize pending metavariables without applying default instances and using the
(mayPostpone := true)
.
4- Tries to compute a maximal type for the tree computed at step 2.
We say a type α is smaller than type β if there is a (nondependent) coercion from α to β.
We are currently ignoring the case we may have cycles in the coercion graph.
If there are "uncomparable" types α and β in the tree, we skip the next step.
We say two types are "uncomparable" if there isn't a coercion between them.
Note that two types may be "uncomparable" because some typing information may still be missing.
5- We traverse the tree and inject coercions to the "maximal" type when needed.
Recall that the coercions are expanded eagerly by the elaborator.
Properties:
a) Given n : Nat
and i : Nat
, it can successfully elaborate n + i
and i + n
. Recall that Lean 3
fails on the former.
b) The coercions are inserted in the "leaves" like in Lean 3.
c) There are no coercions "hidden" inside instances, and we can elaborate
axiom Int.add_comm (i j : Int) : i + j = j + i
example (n : Nat) (i : Int) : n + i = i + n := by
rw [Int.add_comm]
Recall that the rw
tactic used to fail because our old binop%
elaborator would hide
coercions inside of a HAdd
instance.
Remarks:
In the new binop%
and related elaborators the decision whether a coercion will be inserted or not
is made at binop%
elaboration time. This was not the case in the old elaborator.
For example, an instance, such as HAdd Int ?m ?n
, could be created when executing
the binop%
elaborator, and only resolved much later. We try to minimize this problem
by synthesizing pending metavariables at step 3.
For types containing heterogeneous operators (e.g., matrix multiplication), step 4 will fail
and we will skip coercion insertion. For example, x : Matrix Real 5 4
and y : Matrix Real 4 8
,
there is no coercion Matrix Real 5 4
from Matrix Real 4 8
and vice-versa, but
x * y
is elaborated successfully and has type Matrix Real 5 8
.
Elaboration functionf for binrel%
and binrel_no_prop%
notations.
We use the infrastructure for binop%
to make sure we propagate information between the left and right hand sides
of a binary relation.
Recall that the binrel_no_prop%
notation is used for relations such as ==
which do not support Prop
, but
we still want to be able to write (5 > 2) == (2 > 1)
.
Instances For
If noProp == true
and e
has type Prop
, then coerce it to Bool
.